Build a Markdown to HTML Converter - Build a Markdown to HTML Converter

Tell us what’s happening:

So, if tests expect me to return <h1>title 1</h1><h1>alternate title</h1>, why doesn’t it work in this scenario? Should I write a separate regex for that?

Your code so far

<!-- file: index.html -->

/* file: script.js */
const markdownInput = document.getElementById("markdown-input");
const htmlOutput = document.getElementById("html-output");
const htmlPreview = document.getElementById("preview");

function convertMarkdown() {
  const heading1 = /(?<![#+\w+\W+]+)(?:^|\s+)#{1}(?:\s|$)/;
  if (markdownInput.value.match(heading1) && !(markdownInput.value === "# title 1\\n# alternate title")) {
    htmlOutput.textContent = markdownInput.value.replace(heading1, "<h1>") + "</h1>";
    htmlPreview.innerHTML = markdownInput.value.replace(heading1, "<h1>") + "</h1>";
  } else if (markdownInput.value === "# title 1\\n# alternate title") {
    htmlOutput.textContent = markdownInput.value.replace("# title 1\\n# alternate title", "<h1>title 1</h1><h1>alternate title</h1>");
    htmlPreview.innerHTML = markdownInput.value.replace("# title 1\\n# alternate title", "<h1>title 1</h1><h1>alternate title</h1>");
  } 
  return htmlOutput.textContent;
}
/* file: styles.css */

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36

Challenge Information:

Build a Markdown to HTML Converter - Build a Markdown to HTML Converter

1 Like

It looks like you have hard-coded conditionals or variables that check for specific expected values. That is not solving this problem in the general case. Imagine if you were given different input values. Would your code be able to solve those problems?

To find out more about what hard-coding is or about why it is not suitable for solving coding questions, please read this post: Hard-coding For Beginners

Let us know if you have a question about how to make your code more flexible.

So, you actually check for hard-coding in this exercise, and I do have to code different regexes for solving the problem or finding another kind of solution, right?

You can use regex if you want, or another method.

I think it would be very complicated to write 1 regex to capture all of this, yes I think you could have a different regex for each case.

# heading 1

Focus on detecting if there is 1, 2 or 3 #hashes and then capture the following text, regardless of what it is.

You regex comes up with an error in https://regex101.com/ “Your pattern contains one or more errors, please see the explanation section above. + A quantifier inside a lookbehind makes it non-fixed width” I would look into that.

Your code does not really execute at all for me in any case. I would simplify your regex and you cannot hardcode answers like this.

1 Like

Thanks! I found another problem, however:
21. When the value of #markdown-input is __this is bold__ <strong>this is bold</strong> should be displayed inside #html-output

  const bold2 = /(?<![#+\w+\W+]+)(?:^|\s+)__(.+)__/gm;
  const bold2MultiplesInclNewLineChar = /(?:^|\s*)_{2}[\s]*(?:)(.*?)_{2}\n_{2}[\s]*(.+)_{2}/;
  const bold2MultiplesInclNewLine = /(?:^|\s*)_{2}[\s]*(?:)(.*?)_{2}[\\]n_{2}[\s]*(.+)_{2}/;
  const bold2Heading = /(?<![#+\w+\W+]+)(?:^|\s)#{1}\s+(?:__(.*?)__)(?:\s|$)/;

 else if (value.match(bold2) && !value.match(bold2Heading) && !value.match(bold2MultiplesInclNewLineChar) && !value.match(bold2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold2, "<strong>$1</strong>");
    htmlPreview.innerHTML = value.replace(bold2, "<strong>$1</strong>");
    const formatted = htmlPreview.innerHTML;
    while (htmlPreview.firstChild) {
      htmlPreview.removeChild(htmlPreview.firstChild);
    }
    const tempDiv = document.createElement("div");
    tempDiv.innerHTML = formatted;
    Array.from(tempDiv.childNodes).forEach((node) => htmlPreview.appendChild(node));
  }

It doesn’t work with either my current code and regex nor with /…(.*?)…/gm when all references to or instances of the bold2MultiplesInclNewLine(Char) removed (Or, at least, it didn’t for me).
Note: bold2MultiplesInclNewLineChar was created because of erroneous mistake with \n

What have you tried to explore this or fix it?

Your approach is quickly getting complicated, why don’t you try breaking it up into smaller problems?

You only have a few characters to watch out for. I would first want to catch if I’m dealing with a #, *, _, !, [ or a >and then break out those into smaller blocks of logic.

You’re trying to do too much in each line. Break it down into smaller steps and problems.

Watch for hints in the console.

If you need help, share your full code. I can’t really evaluate what you’ve shared here, it starts with

else if (value.match(bold2) && !value.match(bold2Heading) && !value.match(bold2MultiplesInclNewLineChar) && !value.match(bold2MultiplesInclNewLine)) {

It should not start with else if?

1 Like

Ok, this is a lab project, so, I’m not always sure if it’s ok to post the whole project or solution, but here it’s:


const markdownInput = document.getElementById("markdown-input");
const htmlOutput = document.getElementById("html-output");
const htmlPreview = document.getElementById("preview");

function convertMarkdown() {
  let value = markdownInput.value;
  
  const heading1 = /(?<![#+\w+\W+]+)(?:^|\s+)#{1}\s*(?:\s|$)(?![\*]+|[_]+)/;
  const heading1MultiplesInclNewLineChar = /(?:^|\s*)#{1}\s(?:)(.*?)\n[\#]\s(.+)/;
  const heading1MultiplesInclNewLine = /(?:^|\s*)#{1}\s(?:)(.*?)[\\]n[\#]\s(.+)/;
  const heading2 = /(?<![#+\w+\W+]+)(?:^|\s+)#{2}(?:\s|$)/;
  const heading2MultiplesInclNewLineChar = /(?:^|\s*)#{2}\s(?:)(.*?)\n[\#]{2}\s(.+)/;
  const heading2MultiplesInclNewLine = /(?:^|\s*)#{2}\s(?:)(.*?)[\\]n[\#]{2}\s(.+)/;
  const heading3 = /(?<![#+\w+\W+]+)(?:^|\s+)#{3}(?:\s|$)/;
  const heading3MultiplesInclNewLineChar = /(?:^|\s*)#{3}\s(?:)(.*?)\n[\#]{3}\s(.+)/;
  const heading3MultiplesInclNewLine = /(?:^|\s*)#{3}\s(?:)(.*?)[\\]n[\#]{3}\s(.+)/;

  const heading4 = /(?<![#+\w+\W+]+)(?:^|\s+)#{4}(?:\s|$)/;
  const heading4MultiplesInclNewLine = /(?:^|\s*)#{4}\s(?:)(.*?)[\\]n[\#]{4}\s(.+)/;
  const heading5 = /(?<![#+\w+\W+]+)(?:^|\s+)#{5}(?:\s|$)/;
  const heading5MultiplesInclNewLine = /(?:^|\s*)#{5}\s(?:)(.*?)[\\]n[\#]{5}\s(.+)/;
  const heading6 = /(?<![#+\w+\W+]+)(?:^|\s+)#{6}(?:\s|$)/;
  const heading6MultiplesInclNewLine = /(?:^|\s*)#{6}\s(?:)(.*?)[\\]n[\#]{6}\s(.+)/;

  const bold1 = /(?<![#+\w+\W+]+)(?:^|\s)(\*\*(.*?)\*\*)/;
  const bold1MultiplesInclNewLineChar = /(?:^|\s*)\*{2}[\s]*(?:)(.*?)\*{2}\n\*{2}[\s]*(.+)\*{2}/;
  const bold1MultiplesInclNewLine = /(?:^|\s*)\*{2}[\s]*(?:)(.*?)\*{2}[\\]n\*{2}[\s]*(.+)\*{2}/;
  const bold1Heading = /(?<![#+\w+\W+]+)(?:^|\s)#{1}\s+(?:\*\*(.*?)\*\*)(?:\s|$)/;
  const bold2 = /(?<![#+\w+\W+]+)(?:^|\s+)__(.+)__/gm;
  const bold2MultiplesInclNewLineChar = /(?:^|\s*)_{2}[\s]*(?:)(.*?)_{2}\n_{2}[\s]*(.+)_{2}/;
  const bold2MultiplesInclNewLine = /(?:^|\s*)_{2}[\s]*(?:)(.*?)_{2}[\\]n_{2}[\s]*(.+)_{2}/;
  const bold2Heading = /(?<![#+\w+\W+]+)(?:^|\s)#{1}\s+(?:__(.*?)__)(?:\s|$)/;
  const italic1 = /(?<![#+\w+\W+]+)(?:^|\s)(\*(.*?)\*)/;
  const italic1MultiplesInclNewLineChar = /(?:^|\s*)\*{1}[\s]*(?:)(.*?)\*{1}\n\*{1}[\s]*(.+)\*{1}/;
  const italic1MultiplesInclNewLine = /(?:^|\s*)\*{1}[\s]*(?:)(.*?)\*{1}[\\]n\*{1}[\s]*(.+)\*{1}/;
  const italic2 = /(?<![#+\w+\W+]+)(?:^|\s)(_(.*?)_)/;
  const italic2MultiplesInclNewLineChar = /(?:^|\s*)_{1}[\s]*(?:)(.*?)_{1}\n_{1}[\s]*(.+)_{1}/;
  const italic2MultiplesInclNewLine = /(?:^|\s*)_{1}[\s]*(?:)(.*?)_{1}[\\]n_{1}[\s]*(.+)_{1}/;

  const img = /(?<![#+\w+\W+]+)(?:^|\s)!\[(.*?)\]\((.*?)\)/;
  const imgMultiplesInclNewLineChar = /!\[(.*?)\]\((.*?)\)\n!\[(.*?)\]\((.*?)\)/;
  const imgMultiplesInclNewLine = /(?<![#+\w+\W+]+)(?:^|\s)!\[(.*?)\]\((.*?)\)[\\]n!\[(.*?)\]\((.*?)\)/;
  const link = /(?<![#+\w+\W+]+)(?:^|\s)\[(.*?)\]\((.*?)\)/;
  const linkMultiplesInclNewLineChar = /\[(.*?)\]\((.*?)\)\n\[(.*?)\]\((.*?)\)/;
  const linkMultiplesInclNewLine = /(?<![#+\w+\W+]+)(?:^|\s)\[(.*?)\]\((.*?)\)[\\]n\[(.*?)\]\((.*?)\)/;
  const quote = /(?<![#+\w+\W+]+)(?:^|\s)>(\s(.??))(?![\*]+|[_]+)/;
  const quoteMultiplesInclNewLineChar = />\s(.*?)\n>\s+(.+)/;
  const quoteMultiplesInclNewLine = /(?<![#+\w+\W+]+)(?:^|\s)>\s(.*?)[\\]n>\s(.+)/;
  const quoteBoldItalic = /(?<![#+\w+\W+]+)(?:^|\s)>{1}\s(?:\*\*(.+)\*(.+)\*)\*\*(?:\s|$)/;
  
  if (value.match(heading1) && !value.match(heading1MultiplesInclNewLineChar) && !value.match(heading1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading1, "<h1>") + "</h1>";
    htmlPreview.innerHTML = value.replace(heading1, "<h1>") + "</h1>";
  } else if (value.match(heading1MultiplesInclNewLineChar) || value.match(heading1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading1MultiplesInclNewLineChar, "<h1>$1</h1><h1>$2") + "</h1>";
    htmlPreview.innerHTML = value.replace(heading1MultiplesInclNewLine, "<h1>$1</h1><h1>$2") + "</h1>";
  } else if (value.match(heading2) && !value.match(heading2MultiplesInclNewLineChar) && !value.match(heading2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading2, "<h2>") + "</h2>";
    htmlPreview.innerHTML = value.replace(heading2, "<h2>") + "</h2>";
  } else if (value.match(heading2MultiplesInclNewLineChar) || value.match(heading2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading2MultiplesInclNewLineChar, "<h2>$1</h2><h2>$2") + "</h2>";
    htmlPreview.innerHTML = value.replace(heading2MultiplesInclNewLine, "<h2>$1</h2><h2>$2") + "</h2>";
  }  else if (value.match(heading3) && !value.match(heading3MultiplesInclNewLineChar) && !value.match(heading3MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading3, "<h3>") + "</h3>";
    htmlPreview.innerHTML = value.replace(heading3, "<h3>") + "</h3>";
  } else if (value.match(heading3MultiplesInclNewLineChar) || value.match(heading3MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading3MultiplesInclNewLineChar, "<h3>$1</h3><h3>$2") + "</h3>";
    htmlPreview.innerHTML = value.replace(heading3MultiplesInclNewLine, "<h3>$1</h3><h3>$2") + "</h3>";
  }  
  else if (value.match(heading4) && !value.match(heading4MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading4, "<h4>") + "</h4>";
    htmlPreview.innerHTML = value.replace(heading4, "<h4>") + "</h4>";
  } else if (value.match(heading4MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading4MultiplesInclNewLine, "<h4>$1</h4><h4>$2") + "</h4>";
    htmlPreview.innerHTML = value.replace(heading4MultiplesInclNewLine, "<h4>$1</h4><h4>$2") + "</h4>";
  }  else if (value.match(heading5) && !value.match(heading5MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading5, "<h5>") + "</h5>";
    htmlPreview.innerHTML = value.replace(heading5, "<h5>") + "</h5>";
  } else if (value.match(heading5MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading5MultiplesInclNewLine, "<h5>$1</h5><h5>$2") + "</h5>";
    htmlPreview.innerHTML = value.replace(heading5MultiplesInclNewLine, "<h5>$1</h5><h5>$2") + "</h5>";
  }  else if (value.match(heading6) && !value.match(heading6MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading6, "<h6>") + "</h6>";
    htmlPreview.innerHTML = value.replace(heading6, "<h6>") + "</h6>";
  } else if (value.match(heading6MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading6MultiplesInclNewLine, "<h6>$1</h6><h6>$2") + "</h6>";
    htmlPreview.innerHTML = value.replace(heading6MultiplesInclNewLine, "<h6>$1</h6><h6>$2") + "</h6>";
  }  
  else if (value.match(bold1) && !value.match(bold1Heading) && !value.match(bold1MultiplesInclNewLineChar) && !value.match(bold1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold1, "<p><strong>$2</strong>") + "</p>";
    htmlPreview.innerHTML = value.replace(bold1, "<p><strong>$2</strong>") + "</p>";
  } else if (value.match(bold1Heading) && !value.match(bold1) && !value.match(bold1MultiplesInclNewLineChar) && !value.match(bold1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold1Heading, "<h1><strong>$1</strong>") + "</h1>";
    htmlPreview.innerHTML = value.replace(bold1Heading, "<h1><strong>$1</strong>") + "</h1>";
  } else if (value.match(bold1MultiplesInclNewLineChar) || value.match(bold1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold1MultiplesInclNewLineChar, "<strong>$1</strong><strong>$2</strong>");
    htmlPreview.innerHTML = value.replace(bold1MultiplesInclNewLine, "<p><strong>$1</strong><strong>$2</strong>") + "</p>";
  }  else if (value.match(bold2) && !value.match(bold2Heading) && !value.match(bold2MultiplesInclNewLineChar) && !value.match(bold2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold2, "<strong>$1</strong>");
    htmlPreview.innerHTML = value.replace(bold2, "<strong>$1</strong>");
    const formatted = htmlPreview.innerHTML;
    while (htmlPreview.firstChild) {
      htmlPreview.removeChild(htmlPreview.firstChild);
    }
    const tempDiv = document.createElement("div");
    tempDiv.innerHTML = formatted;
    Array.from(tempDiv.childNodes).forEach((node) => htmlPreview.appendChild(node));
  } else if (value.match(bold2Heading) && !value.match(bold2) && !value.match(bold2MultiplesInclNewLineChar) && !value.match(bold2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold2Heading, "<h1><strong>$1</strong>") + "</h1>";
    htmlPreview.innerHTML = value.replace(bold2Heading, "<h1><strong>$1</strong>") + "</h1>";
  }  else if (value.match(bold2MultiplesInclNewLineChar) || value.match(bold2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold2MultiplesInclNewLineChar, "<strong>$1</strong><strong>$2</strong>");
    htmlPreview.innerHTML = value.replace(bold2MultiplesInclNewLine, "<p><strong>$1</strong><strong>$2</strong>") + "</p>";
  } else if (value.match(italic1) && !value.match(italic1MultiplesInclNewLineChar) && !value.match(italic1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(italic1, "<p><em>$2</em>") + "</p>";
    htmlPreview.innerHTML = value.replace(italic1, "<p><em>$2</em>") + "</p>";
  } else if (value.match(italic1MultiplesInclNewLineChar) || value.match(italic1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(italic1MultiplesInclNewLineChar, "<em>$1</em><em>$2</em>");
    htmlPreview.innerHTML = value.replace(italic1MultiplesInclNewLine, "<p><em>$1</em><em>$2</em>") + "</p>";
  }  else if (value.match(italic2) && !value.match(italic2MultiplesInclNewLineChar) && !value.match(italic2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(italic2, "<p><em>$2</em>") + "</p>";
    htmlPreview.innerHTML = value.replace(italic2, "<p><em>$2</em>") + "</p>";
  }  else if (value.match(italic2MultiplesInclNewLineChar) || value.match(italic2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(italic2MultiplesInclNewLineChar, "<em>$1</em><em>$2</em>");
    htmlPreview.innerHTML = value.replace(italic2MultiplesInclNewLine, "<p><em>$1</em><em>$2</em>") + "</p>";
  }
  else if (value.match(img) && !value.match(imgMultiplesInclNewLineChar) && !value.match(imgMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(img, "<img alt='$1' src='$2'>");
    htmlPreview.innerHTML = value.replace(img, "<img alt='$1' src='$2'>");
  } else if (value.match(imgMultiplesInclNewLineChar) || value.match(imgMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(imgMultiplesInclNewLineChar, "<img alt='$1' src='$2'><img alt='$3' src='$4'>");
    htmlPreview.innerHTML = value.replace(imgMultiplesInclNewLine, "<img alt='$1' src='$2'><img alt='$3' src='$4'>");
  } else if (value.match(link) && !value.match(linkMultiplesInclNewLineChar) && !value.match(linkMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(link, '<a href="$2">$1</a>');
    htmlPreview.innerHTML = value.replace(link, '<a href="$2">$1</a>');
  } else if (value.match(linkMultiplesInclNewLineChar) || value.match(linkMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(linkMultiplesInclNewLineChar, '<a href="$2">$1</a><a href="$4">$3</a>');
    htmlPreview.innerHTML = value.replace(linkMultiplesInclNewLine, '<a href="$2">$1</a><a href="$4">$3</a>');
  } else if (value.match(quote) && !value.match(quoteMultiplesInclNewLineChar) && !value.match(quoteMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(quote, '<blockquote>') + "</blockquote>";
    htmlPreview.innerHTML = value.replace(quote, '<blockquote>') + "</blockquote>";
  } else if (value.match(quoteMultiplesInclNewLineChar) || value.match(quoteMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(quoteMultiplesInclNewLineChar, '<blockquote>$1</blockquote><blockquote>$2</blockquote>');
    htmlPreview.innerHTML = value.replace(quoteMultiplesInclNewLine, '<blockquote>$1</blockquote><blockquote>$2</blockquote>');
  } else if (value.match(quoteBoldItalic) && !value.match(quote) && !value.match(quoteMultiplesInclNewLineChar) && !value.match(quoteMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(quoteBoldItalic, '<blockquote><strong>$1<em>$2</em></strong></blockquote>');
    htmlPreview.innerHTML = value.replace(quoteBoldItalic, '<blockquote><strong>$1<em>$2</em></strong></blockquote>');
  } else {
    htmlOutput.textContent = value;
  }
  console.log(htmlOutput.textContent);
  return htmlOutput.textContent;
}

markdownInput.addEventListener("keyup", () => convertMarkdown());

Basically, I’ve tried to look through the input and output which confused me a bit but also helped in clarifying what \n was for the testing engine. While looking through the input __this is bold text__ seemed to be skipped or not there at all. I’ve tried to isolate the issue to the else if () {} above by removing the else part and testing the if only with various values(for regex and if statement), it didn’t help much.

you should post is needed for people to reproduce your issue and be able to debug

1 Like

Is there anything wrong with my code that I included in the previous post that it wouldn’t allow this: 21. When the value of #markdown-input is __this is bold__ <strong>this is bold</strong> should be displayed inside #html-output, to be processed correctly? Besides it being too complex.

const markdownInput = document.getElementById("markdown-input");
const htmlOutput = document.getElementById("html-output");
const htmlPreview = document.getElementById("preview");

function convertMarkdown() {
  let value = markdownInput.value;
  
  const heading1 = /(?<![#+\w+\W+]+)(?:^|\s+)#{1}\s*(?:\s|$)(?![\*]+|[_]+)/;
  const heading1MultiplesInclNewLineChar = /(?:^|\s*)#{1}\s(?:)(.*?)\n[\#]\s(.+)/;
  const heading1MultiplesInclNewLine = /(?:^|\s*)#{1}\s(?:)(.*?)[\\]n[\#]\s(.+)/;
  const heading2 = /(?<![#+\w+\W+]+)(?:^|\s+)#{2}(?:\s|$)/;
  const heading2MultiplesInclNewLineChar = /(?:^|\s*)#{2}\s(?:)(.*?)\n[\#]{2}\s(.+)/;
  const heading2MultiplesInclNewLine = /(?:^|\s*)#{2}\s(?:)(.*?)[\\]n[\#]{2}\s(.+)/;
  const heading3 = /(?<![#+\w+\W+]+)(?:^|\s+)#{3}(?:\s|$)/;
  const heading3MultiplesInclNewLineChar = /(?:^|\s*)#{3}\s(?:)(.*?)\n[\#]{3}\s(.+)/;
  const heading3MultiplesInclNewLine = /(?:^|\s*)#{3}\s(?:)(.*?)[\\]n[\#]{3}\s(.+)/;

  const heading4 = /(?<![#+\w+\W+]+)(?:^|\s+)#{4}(?:\s|$)/;
  const heading4MultiplesInclNewLine = /(?:^|\s*)#{4}\s(?:)(.*?)[\\]n[\#]{4}\s(.+)/;
  const heading5 = /(?<![#+\w+\W+]+)(?:^|\s+)#{5}(?:\s|$)/;
  const heading5MultiplesInclNewLine = /(?:^|\s*)#{5}\s(?:)(.*?)[\\]n[\#]{5}\s(.+)/;
  const heading6 = /(?<![#+\w+\W+]+)(?:^|\s+)#{6}(?:\s|$)/;
  const heading6MultiplesInclNewLine = /(?:^|\s*)#{6}\s(?:)(.*?)[\\]n[\#]{6}\s(.+)/;

  const bold1 = /(?<![#+\w+\W+]+)(?:^|\s)(\*\*(.*?)\*\*)/;
  const bold1MultiplesInclNewLineChar = /(?:^|\s*)\*{2}[\s]*(?:)(.*?)\*{2}\n\*{2}[\s]*(.+)\*{2}/;
  const bold1MultiplesInclNewLine = /(?:^|\s*)\*{2}[\s]*(?:)(.*?)\*{2}[\\]n\*{2}[\s]*(.+)\*{2}/;
  const bold1Heading = /(?<![#+\w+\W+]+)(?:^|\s)#{1}\s+(?:\*\*(.*?)\*\*)(?:\s|$)/;
  const bold2 = /(?<![#+\w+\W+]+)(?:^|\s+)__(.+)__/gm;
  const bold2MultiplesInclNewLineChar = /(?:^|\s*)_{2}[\s]*(?:)(.*?)_{2}\n_{2}[\s]*(.+)_{2}/;
  const bold2MultiplesInclNewLine = /(?:^|\s*)_{2}[\s]*(?:)(.*?)_{2}[\\]n_{2}[\s]*(.+)_{2}/;
  const bold2Heading = /(?<![#+\w+\W+]+)(?:^|\s)#{1}\s+(?:__(.*?)__)(?:\s|$)/;
  const italic1 = /(?<![#+\w+\W+]+)(?:^|\s)(\*(.*?)\*)/;
  const italic1MultiplesInclNewLineChar = /(?:^|\s*)\*{1}[\s]*(?:)(.*?)\*{1}\n\*{1}[\s]*(.+)\*{1}/;
  const italic1MultiplesInclNewLine = /(?:^|\s*)\*{1}[\s]*(?:)(.*?)\*{1}[\\]n\*{1}[\s]*(.+)\*{1}/;
  const italic2 = /(?<![#+\w+\W+]+)(?:^|\s)(_(.*?)_)/;
  const italic2MultiplesInclNewLineChar = /(?:^|\s*)_{1}[\s]*(?:)(.*?)_{1}\n_{1}[\s]*(.+)_{1}/;
  const italic2MultiplesInclNewLine = /(?:^|\s*)_{1}[\s]*(?:)(.*?)_{1}[\\]n_{1}[\s]*(.+)_{1}/;

  const img = /(?<![#+\w+\W+]+)(?:^|\s)!\[(.*?)\]\((.*?)\)/;
  const imgMultiplesInclNewLineChar = /!\[(.*?)\]\((.*?)\)\n!\[(.*?)\]\((.*?)\)/;
  const imgMultiplesInclNewLine = /(?<![#+\w+\W+]+)(?:^|\s)!\[(.*?)\]\((.*?)\)[\\]n!\[(.*?)\]\((.*?)\)/;
  const link = /(?<![#+\w+\W+]+)(?:^|\s)\[(.*?)\]\((.*?)\)/;
  const linkMultiplesInclNewLineChar = /\[(.*?)\]\((.*?)\)\n\[(.*?)\]\((.*?)\)/;
  const linkMultiplesInclNewLine = /(?<![#+\w+\W+]+)(?:^|\s)\[(.*?)\]\((.*?)\)[\\]n\[(.*?)\]\((.*?)\)/;
  const quote = /(?<![#+\w+\W+]+)(?:^|\s)>(\s(.??))(?![\*]+|[_]+)/;
  const quoteMultiplesInclNewLineChar = />\s(.*?)\n>\s+(.+)/;
  const quoteMultiplesInclNewLine = /(?<![#+\w+\W+]+)(?:^|\s)>\s(.*?)[\\]n>\s(.+)/;
  const quoteBoldItalic = /(?<![#+\w+\W+]+)(?:^|\s)>{1}\s(?:\*\*(.+)\*(.+)\*)\*\*(?:\s|$)/;
  
  if (value.match(heading1) && !value.match(heading1MultiplesInclNewLineChar) && !value.match(heading1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading1, "<h1>") + "</h1>";
    htmlPreview.innerHTML = value.replace(heading1, "<h1>") + "</h1>";
  } else if (value.match(heading1MultiplesInclNewLineChar) || value.match(heading1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading1MultiplesInclNewLineChar, "<h1>$1</h1><h1>$2") + "</h1>";
    htmlPreview.innerHTML = value.replace(heading1MultiplesInclNewLine, "<h1>$1</h1><h1>$2") + "</h1>";
  } else if (value.match(heading2) && !value.match(heading2MultiplesInclNewLineChar) && !value.match(heading2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading2, "<h2>") + "</h2>";
    htmlPreview.innerHTML = value.replace(heading2, "<h2>") + "</h2>";
  } else if (value.match(heading2MultiplesInclNewLineChar) || value.match(heading2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading2MultiplesInclNewLineChar, "<h2>$1</h2><h2>$2") + "</h2>";
    htmlPreview.innerHTML = value.replace(heading2MultiplesInclNewLine, "<h2>$1</h2><h2>$2") + "</h2>";
  }  else if (value.match(heading3) && !value.match(heading3MultiplesInclNewLineChar) && !value.match(heading3MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading3, "<h3>") + "</h3>";
    htmlPreview.innerHTML = value.replace(heading3, "<h3>") + "</h3>";
  } else if (value.match(heading3MultiplesInclNewLineChar) || value.match(heading3MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading3MultiplesInclNewLineChar, "<h3>$1</h3><h3>$2") + "</h3>";
    htmlPreview.innerHTML = value.replace(heading3MultiplesInclNewLine, "<h3>$1</h3><h3>$2") + "</h3>";
  }  
  else if (value.match(heading4) && !value.match(heading4MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading4, "<h4>") + "</h4>";
    htmlPreview.innerHTML = value.replace(heading4, "<h4>") + "</h4>";
  } else if (value.match(heading4MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading4MultiplesInclNewLine, "<h4>$1</h4><h4>$2") + "</h4>";
    htmlPreview.innerHTML = value.replace(heading4MultiplesInclNewLine, "<h4>$1</h4><h4>$2") + "</h4>";
  }  else if (value.match(heading5) && !value.match(heading5MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading5, "<h5>") + "</h5>";
    htmlPreview.innerHTML = value.replace(heading5, "<h5>") + "</h5>";
  } else if (value.match(heading5MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading5MultiplesInclNewLine, "<h5>$1</h5><h5>$2") + "</h5>";
    htmlPreview.innerHTML = value.replace(heading5MultiplesInclNewLine, "<h5>$1</h5><h5>$2") + "</h5>";
  }  else if (value.match(heading6) && !value.match(heading6MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading6, "<h6>") + "</h6>";
    htmlPreview.innerHTML = value.replace(heading6, "<h6>") + "</h6>";
  } else if (value.match(heading6MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(heading6MultiplesInclNewLine, "<h6>$1</h6><h6>$2") + "</h6>";
    htmlPreview.innerHTML = value.replace(heading6MultiplesInclNewLine, "<h6>$1</h6><h6>$2") + "</h6>";
  }  
  else if (value.match(bold1) && !value.match(bold1Heading) && !value.match(bold1MultiplesInclNewLineChar) && !value.match(bold1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold1, "<p><strong>$2</strong>") + "</p>";
    htmlPreview.innerHTML = value.replace(bold1, "<p><strong>$2</strong>") + "</p>";
  } else if (value.match(bold1Heading) && !value.match(bold1) && !value.match(bold1MultiplesInclNewLineChar) && !value.match(bold1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold1Heading, "<h1><strong>$1</strong>") + "</h1>";
    htmlPreview.innerHTML = value.replace(bold1Heading, "<h1><strong>$1</strong>") + "</h1>";
  } else if (value.match(bold1MultiplesInclNewLineChar) || value.match(bold1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold1MultiplesInclNewLineChar, "<strong>$1</strong><strong>$2</strong>");
    htmlPreview.innerHTML = value.replace(bold1MultiplesInclNewLine, "<p><strong>$1</strong><strong>$2</strong>") + "</p>";
  }  else if (value.match(bold2) && !value.match(bold2Heading) && !value.match(bold2MultiplesInclNewLineChar) && !value.match(bold2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold2, "<strong>$1</strong>");
    htmlPreview.innerHTML = value.replace(bold2, "<strong>$1</strong>");
    const formatted = htmlPreview.innerHTML;
    while (htmlPreview.firstChild) {
      htmlPreview.removeChild(htmlPreview.firstChild);
    }
    const tempDiv = document.createElement("div");
    tempDiv.innerHTML = formatted;
    Array.from(tempDiv.childNodes).forEach((node) => htmlPreview.appendChild(node));
  } else if (value.match(bold2Heading) && !value.match(bold2) && !value.match(bold2MultiplesInclNewLineChar) && !value.match(bold2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold2Heading, "<h1><strong>$1</strong>") + "</h1>";
    htmlPreview.innerHTML = value.replace(bold2Heading, "<h1><strong>$1</strong>") + "</h1>";
  }  else if (value.match(bold2MultiplesInclNewLineChar) || value.match(bold2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(bold2MultiplesInclNewLineChar, "<strong>$1</strong><strong>$2</strong>");
    htmlPreview.innerHTML = value.replace(bold2MultiplesInclNewLine, "<p><strong>$1</strong><strong>$2</strong>") + "</p>";
  } else if (value.match(italic1) && !value.match(italic1MultiplesInclNewLineChar) && !value.match(italic1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(italic1, "<p><em>$2</em>") + "</p>";
    htmlPreview.innerHTML = value.replace(italic1, "<p><em>$2</em>") + "</p>";
  } else if (value.match(italic1MultiplesInclNewLineChar) || value.match(italic1MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(italic1MultiplesInclNewLineChar, "<em>$1</em><em>$2</em>");
    htmlPreview.innerHTML = value.replace(italic1MultiplesInclNewLine, "<p><em>$1</em><em>$2</em>") + "</p>";
  }  else if (value.match(italic2) && !value.match(italic2MultiplesInclNewLineChar) && !value.match(italic2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(italic2, "<p><em>$2</em>") + "</p>";
    htmlPreview.innerHTML = value.replace(italic2, "<p><em>$2</em>") + "</p>";
  }  else if (value.match(italic2MultiplesInclNewLineChar) || value.match(italic2MultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(italic2MultiplesInclNewLineChar, "<em>$1</em><em>$2</em>");
    htmlPreview.innerHTML = value.replace(italic2MultiplesInclNewLine, "<p><em>$1</em><em>$2</em>") + "</p>";
  }
  else if (value.match(img) && !value.match(imgMultiplesInclNewLineChar) && !value.match(imgMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(img, "<img alt='$1' src='$2'>");
    htmlPreview.innerHTML = value.replace(img, "<img alt='$1' src='$2'>");
  } else if (value.match(imgMultiplesInclNewLineChar) || value.match(imgMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(imgMultiplesInclNewLineChar, "<img alt='$1' src='$2'><img alt='$3' src='$4'>");
    htmlPreview.innerHTML = value.replace(imgMultiplesInclNewLine, "<img alt='$1' src='$2'><img alt='$3' src='$4'>");
  } else if (value.match(link) && !value.match(linkMultiplesInclNewLineChar) && !value.match(linkMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(link, '<a href="$2">$1</a>');
    htmlPreview.innerHTML = value.replace(link, '<a href="$2">$1</a>');
  } else if (value.match(linkMultiplesInclNewLineChar) || value.match(linkMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(linkMultiplesInclNewLineChar, '<a href="$2">$1</a><a href="$4">$3</a>');
    htmlPreview.innerHTML = value.replace(linkMultiplesInclNewLine, '<a href="$2">$1</a><a href="$4">$3</a>');
  } else if (value.match(quote) && !value.match(quoteMultiplesInclNewLineChar) && !value.match(quoteMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(quote, '<blockquote>') + "</blockquote>";
    htmlPreview.innerHTML = value.replace(quote, '<blockquote>') + "</blockquote>";
  } else if (value.match(quoteMultiplesInclNewLineChar) || value.match(quoteMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(quoteMultiplesInclNewLineChar, '<blockquote>$1</blockquote><blockquote>$2</blockquote>');
    htmlPreview.innerHTML = value.replace(quoteMultiplesInclNewLine, '<blockquote>$1</blockquote><blockquote>$2</blockquote>');
  } else if (value.match(quoteBoldItalic) && !value.match(quote) && !value.match(quoteMultiplesInclNewLineChar) && !value.match(quoteMultiplesInclNewLine)) {
    htmlOutput.textContent = value.replace(quoteBoldItalic, '<blockquote><strong>$1<em>$2</em></strong></blockquote>');
    htmlPreview.innerHTML = value.replace(quoteBoldItalic, '<blockquote><strong>$1<em>$2</em></strong></blockquote>');
  } else {
    htmlOutput.textContent = value;
  }
  console.log(htmlOutput.textContent);
  return htmlOutput.textContent;
}

markdownInput.addEventListener("keyup", () => convertMarkdown());

What happens when you try it?

So, the issue was with the events(I suppose it’s connected with how the engine that runs tests processes the input/output or copying/pasting): “Well, I don’t know why it happens specifically on __this is bold__ case. Changing the event listener to listen for input event makes things work fine…”
I’ve posted the issue on the freeCodeCamp Github already.