Build a Markdown to HTML Converter - Can't pass 49 of 51 tests

Tell us what’s happening:

I cannot pass any of the tests other than 1 and 51 even though I think my program should work for at least one or two of the regexs. There are probably many things wrong with my program - so for purposes of this question I’m just going to focus on the headings.

Does anyone know why my program is not working as to only the headings levels 1-3 ? (tests 2-16). Any help or guidance is appreciated. I’ll deal with trying to make the rest work in separate posts, if needed.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Markdown to HTML Converter</title>
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <h1>Markdown to HTML Converter</h1>
    <div id="container">
        <div class="container">
            <h2>Markdown Input:</h2>
            <textarea id="markdown-input" placeholder="Enter your markdown here..."></textarea>
        </div>
        <div class="container">
            <h2>Raw HTML Output:</h2>
            <div id="html-output"></div>
        </div>
        <div class="container">
            <h2>HTML Preview:</h2>
            <div id="preview"></div>
        </div>
    </div>
    <script src="script.js"></script>
</body>

</html>
/* file: styles.css */
* {
     box-sizing: border-box;
}
 body {
     font-family: Arial, sans-serif;
     padding: 20px;
}
 #markdown-input {
     width: 100%;
     height: 100px;
}
 #html-output, #preview {
     height: 100px;
     display: inline-block;
     width: 100%;
     border: 1px solid #ccc;
     padding: 10px;
     margin: auto;
     white-space: pre-wrap;
     background-color: #f9f9f9;
}
 @media (min-width: 600px) {
     #markdown-input, #html-output, #preview {
         height: 200px;
         margin: 0;
    }
     #container {
         display: flex;
         justify-content: space-evenly;
         gap: 10px;
    }
}
/* file: script.js */
const markdownInput = document.getElementById("markdown-input");
const preview = document.getElementById("preview");
const htmlOutput = document.getElementById("html-output");
const h1RegExObj = {
  regEx: /(\s+|^)#\s(\w+)/,
  replace: "<h1>$2</h1>",
};
const h2RegExObj = {
  regEx: /(\s+|^)##\s(\w+)/,
  replace: "<h2>$2</h2>",
};
const h3RegExObj = {
  regEx: /(\s+|^)###\s(\w+)/,
  replace: "<h3>$2</h3>",
};
const strongRegExObj = {
  regEx: /(\s+|^)(\*\*|__)(\w+)\2/,
  replace: "<strong>$3</strong>",
};
const emRegExObj = {
  regEx: /(\s+|^)(\*|_)(\w+)\2/,
  replace: "<em>$3</em>",
};
const imgRegExObj = {
  regEx: /(\s+|^)(\!\[.*?\]\((.*?)\))/,
  replace: "<img src=\"$3\" alt=\"$1\" />",
};
const aRegExObj = {
  regEx: /(\s+|^)(\[.*?\]\((.*?)\))/,
  replace: "<a href=\"$3\">$1</a>",
};
const blockquoteRegExObj = {
  regEx: /(\s+|^)(>)(.*)/,
  replace: "<blockquote>$3</blockquote>",
};
const regExObjArr = [h1RegExObj, h2RegExObj, h3RegExObj, strongRegExObj, emRegExObj, imgRegExObj, aRegExObj, blockquoteRegExObj];

function convertMarkdown() {
  const returnStringArr = [];
  const markdownInputArr = markdownInput.value.split(/\r?\n|\r|\n/g);
  console.log(markdownInputArr);

  markdownInputArr.forEach((line) => {
    let lineProcessed = false;

    for (const regExObj of regExObjArr) {
      if (regExObj.regEx.test(line)) {
        const processedLine = line.replace(regExObj.regEx, regExObj.replace);
        returnStringArr.push(processedLine);
        lineProcessed = true;
        break; // Stop after first match
      }
    }

    if (!lineProcessed) {
      returnStringArr.push(line);
    }
  });
  const returnStringStr = returnStringArr.join("\n");

  // Update the preview and htmlOutput elements each keypress
  preview.innerHTML = "";
  preview.innerHTML = returnStringStr;
  htmlOutput.innerText = "";
  htmlOutput.innerText = returnStringStr;
  return returnStringStr;
}

markdownInput.addEventListener("input", convertMarkdown);

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0

Challenge Information:

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

have you tested your app?

you are putting the 1 outside the h1 element, everything on the same line goes inside the h1 element

I did test my app, but obviously very poorly. So in this case, I was testing my code without spaces first so I didn’t see what you pointed out. My thought was to test the most simple version first. In any case, I was able to find the problem with that regex. I’m able to get test 1-31,51 passing, which is great. However, now I’m stuck on test 32 and 33.

I’m not sure how to deal with these without a significant rewrite of my code. When writing it, I realized I’d have to compare each line to a regex, but I didn’t realize I’d have to apply more than one regex to a line. So I’m trying to decide whether to do an additional regex that’s more specific than the current h1 and em regexs and test for it first. An additional combined h1 / em regex is not a very robust solution - and would not work unless I did the same thing for every heading combination, but maybe it’s sufficient for this project?

I guess my question is does it make sense to rewrite my code from the beginning or add a more specific h1/em combo regex?

const markdownInput = document.getElementById("markdown-input");
const preview = document.getElementById("preview");
const htmlOutput = document.getElementById("html-output");
const h1RegExObj = {
  regEx: /(^\s+|^)#\s+(.+)/,
  replace: "<h1>$2</h1>",
};
const h2RegExObj = {
  regEx: /(^\s+|^)##\s+(.+)/,
  replace: "<h2>$2</h2>",
};
const h3RegExObj = {
  regEx: /(^\s+|^)###\s+(.+)/,
  replace: "<h3>$2</h3>",
};
const strongRegExObj = {
  regEx: /(\*\*|__)(\w+.+)(\*\*|__)/,
  replace: "<strong>$2</strong>",
};
const emRegExObj = {
  regEx: /(\*|_)(\w+.+)(\*|_)/,
  replace: "<em>$2</em>",
};
// Regexs above working, below not working.
const imgRegExObj = {
  regEx: /(\s+|^)(\!\[.*?\]\((.*?)\))/,
  replace: '<img src="$3" alt="$1" />',
};
const aRegExObj = {
  regEx: /(\s+|^)(\[.*?\]\((.*?)\))/,
  replace: '<a href="$3">$1</a>',
};
const blockquoteRegExObj = {
  regEx: /(\s+|^)(>)(.*)/,
  replace: "<blockquote>$3</blockquote>",
};
const regExObjArr = [
  h1RegExObj,
  h2RegExObj,
  h3RegExObj,
  strongRegExObj,
  emRegExObj,
  imgRegExObj,
  aRegExObj,
  blockquoteRegExObj,
];

function convertMarkdown() {
  const returnStringArr = [];
  const markdownInputArr = markdownInput.value.split(/\r?\n|\r|\n/g);
  console.log(markdownInputArr);

  markdownInputArr.forEach((line) => {
    let lineProcessed = false;

    for (const regExObj of regExObjArr) {
      if (regExObj.regEx.test(line)) {
        const processedLine = line.replace(regExObj.regEx, regExObj.replace);
        returnStringArr.push(processedLine);
        lineProcessed = true;
        break; // Stop after first match
      }
    }

    if (!lineProcessed) {
      returnStringArr.push(line);
    }
  });
  const returnStringStr = returnStringArr.join("\n");

  // Update the preview and htmlOutput elements each keypress
  preview.innerHTML = "";
  preview.innerHTML = returnStringStr;
  htmlOutput.innerText = "";
  htmlOutput.innerText = returnStringStr;
  return returnStringStr;
}

markdownInput.addEventListener("input", convertMarkdown);

you can do whichever you prefer, the goal for this is not to create a fully functional markdown parser, but to make you work with regex