diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json
index b441c6ba3e2..375798ba044 100644
--- a/client/i18n/locales/english/intro.json
+++ b/client/i18n/locales/english/intro.json
@@ -2776,9 +2776,14 @@
"Test what you've learned in this quiz on Debugging JavaScript."
]
},
- "dqth": { "title": "205", "intro": [] },
- "ilop": { "title": "206", "intro": [] },
- "qrer": { "title": "207", "intro": [] },
+ "ilop": { "title": "205", "intro": [] },
+ "dqth": { "title": "206", "intro": [] },
+ "lab-markdown-to-html-converter": {
+ "title": "Build a Markdown to HTML Converter",
+ "intro": [
+ "For this lab, you will build a Markdown to HTML converter using JavaScript."
+ ]
+ },
"lab-regex-sandbox": {
"title": "Build a RegEx Sandbox",
"intro": ["In this lab you will build a regex sandbox."]
diff --git a/client/src/pages/learn/full-stack-developer/lab-markdown-to-html-converter/index.md b/client/src/pages/learn/full-stack-developer/lab-markdown-to-html-converter/index.md
new file mode 100644
index 00000000000..110f48e51d4
--- /dev/null
+++ b/client/src/pages/learn/full-stack-developer/lab-markdown-to-html-converter/index.md
@@ -0,0 +1,9 @@
+---
+title: Introduction to the Build a Markdown to HTML Converter
+block: lab-markdown-to-html-converter
+superBlock: full-stack-developer
+---
+
+## Introduction to the Build a Markdown to HTML Converter
+
+For this lab, you will build a Markdown to HTML converter using JavaScript.
diff --git a/curriculum/challenges/_meta/lab-markdown-to-html-converter/meta.json b/curriculum/challenges/_meta/lab-markdown-to-html-converter/meta.json
new file mode 100644
index 00000000000..4eec16add9f
--- /dev/null
+++ b/curriculum/challenges/_meta/lab-markdown-to-html-converter/meta.json
@@ -0,0 +1,11 @@
+{
+ "name": "Build a Markdown to HTML Converter",
+ "isUpcomingChange": true,
+ "usesMultifileEditor": true,
+ "blockType": "lab",
+ "blockLayout": "link",
+ "dashedName": "lab-markdown-to-html-converter",
+ "superBlock": "full-stack-developer",
+ "challengeOrder": [{ "id": "66f55eac933ff64ce654ca74", "title": "Build a Markdown to HTML Converter" }],
+ "helpCategory": "JavaScript"
+}
diff --git a/curriculum/challenges/english/25-front-end-development/lab-markdown-to-html-converter/66f55eac933ff64ce654ca74.md b/curriculum/challenges/english/25-front-end-development/lab-markdown-to-html-converter/66f55eac933ff64ce654ca74.md
new file mode 100644
index 00000000000..f21024640fc
--- /dev/null
+++ b/curriculum/challenges/english/25-front-end-development/lab-markdown-to-html-converter/66f55eac933ff64ce654ca74.md
@@ -0,0 +1,906 @@
+---
+id: 66f55eac933ff64ce654ca74
+title: Build a Markdown to HTML Converter
+challengeType: 14
+dashedName: build-a-markdown-to-html-converter
+demoType: onClick
+---
+
+# --description--
+
+Markdown is a markup language used to add formatting elements to plain-text documents. For this lab, all the HTML and CSS has been provided to you. You will use JavaScript to complete the Markdown to HTML Converter app so that it can handle the conversion of basic Markdown constructs into HTML elements.
+
+**Note:** The final result won't be a comprehensive Markdown to HTML converter, but you can add extra functionalities to it if you would like.
+
+**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
+
+**User Stories:**
+
+1. You should have a function named `convertMarkdown` that takes no parameters.
+1. The `convertMarkdown` function should use regular expressions to convert the markdown input from `#markdown-input` into HTML and should return a string containing the HTML code.
+1. The `convertMarkdown` function should convert headings of level one, two, and three into the corresponding `h1`, `h2`, and `h3` elements. A heading in markdown is indicated by as many `#` character as its level followed by a space and the heading text. `#` characters should either be placed at the beginning of the line or be preceded by space characters.
+1. The `convertMarkdown` function should convert bold text into `strong` elements. Bold text in markdown is indicated either by a pair of double asterisks or a pair of double underscores enclosing the text.
+1. The `convertMarkdown` function should convert italic text into `em` elements. Italic text in markdown is indicated either by a pair of asterisks or a pair of underscores enclosing the text.
+1. The `convertMarkdown` function should convert images into `img` elements. An image in markdown is indicated by ``, where `alt-text` is the value of the `alt` attribute and `image-source` is the value of the `src` attribute.
+1. The `convertMarkdown` function should convert links into anchor elements. A link in markdown is indicated by `[link text](URL)`, where `link text` is the text to enclosed within the anchor tags and `URL` is the value of `href` attribute.
+1. The `convertMarkdown` function should convert quotes into `blockquote` elements. A quote in markdown is indicated by a `>` followed by a space and the quote text. The `>` character should be either placed at the beginning of the line or be preceded by space characters.
+1. When you input text inside `#markdown-input`, the raw HTML code returned by `convertMarkdown` should be displayed inside `#html-output`.
+1. When you input text inside `#markdown-input`, the HTML code returned by `convertMarkdown` should be rendered inside `#preview`.
+
+Here's a table containing all the markdown that `convertMarkdown` should be able to handle and the expected HTML after conversion:
+
+
+
+
+
Markdown
+
HTML
+
+
+
+
+
# heading 1
+
<h1>heading 1</h1>
+
+
+
## heading 2
+
<h2>heading 2</h2>
+
+
+
### heading 3
+
<h3>heading 3</h3>
+
+
+
**bold text** or __bold text__
+
<strong>bold text</strong>
+
+
+
*italic text* or _italic text_
+
<em>italic text</em>
+
+
+

+
<img alt="alt-text" src="image-source">
+
+
+
[link text](URL)
+
<a href="URL">link text</a>
+
+
+
> quote
+
<blockquote>quote</blockquote>
+
+
+
+
+**Note:** Be sure to link your JavaScript file in your HTML.
+
+# --hints--
+
+You should have a function named `convertMarkdown`.
+
+```js
+assert.isFunction(convertMarkdown);
+```
+
+When the value of `#markdown-input` is `# title 1`, `convertMarkdown()` should return `
title 1
`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "# title 1";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const headings = testDiv.querySelectorAll("h1");
+assert.lengthOf(headings, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(headings[0].innerText, "title 1");
+```
+
+When the value of `#markdown-input` is `# title 1`, `
title 1
` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "# title 1";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const headings = testDiv.querySelectorAll("h1");
+assert.lengthOf(headings, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(headings[0].innerText, "title 1");
+```
+
+When the value of `#markdown-input` is `# title 1`, an `h1` element with the text of `title 1` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "# title 1";
+input.dispatchEvent(new Event("input"));
+const headings = preview.querySelectorAll("h1");
+assert.lengthOf(headings, 1);
+assert.lengthOf(preview.children, 1);
+assert.equal(headings[0].innerText, "title 1");
+```
+
+When the value of `#markdown-input` is `some text # title 1`, `convertMarkdown()` should not convert `# title 1` into an `h1` element.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "some text # title 1";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const testH1 = testDiv.querySelector("h1")
+assert.notExists(testH1);
+```
+
+When the value of `#markdown-input` is `## title 2`, `convertMarkdown()` should return `
title 2
`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "## title 2";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const headings = testDiv.querySelectorAll("h2");
+assert.lengthOf(headings, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(headings[0].innerText, "title 2");
+```
+
+When the value of `#markdown-input` is `## title 2`, `
title 2
` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "## title 2";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const headings = testDiv.querySelectorAll("h2");
+assert.lengthOf(headings, 1);
+assert.lengthOf(testDiv.children, 1)
+assert.equal(headings[0].innerText, "title 2");
+```
+
+When the value of `#markdown-input` is `## title 2`, an `h2` element with the text of `title 2` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "## title 2";
+input.dispatchEvent(new Event("input"));
+const headings = preview.querySelectorAll("h2");
+assert.lengthOf(headings, 1);
+assert.lengthOf(preview.children, 1)
+assert.equal(headings[0].innerText, "title 2");
+```
+
+When the value of `#markdown-input` is `some text ## title 2`, `convertMarkdown()` should not convert `## title 2` into an `h2` element.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "some text ## title 2";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const testH2 = testDiv.querySelector("h2")
+assert.notExists(testH2);
+```
+
+When the value of `#markdown-input` is `### title 3`, `convertMarkdown()` should return `
title 3
`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "### title 3";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const headings = testDiv.querySelectorAll("h3");
+assert.lengthOf(headings, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(headings[0].innerText, "title 3");
+```
+
+When the value of `#markdown-input` is `### title 3`, `
title 3
` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "### title 3";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const headings = testDiv.querySelectorAll("h3");
+assert.lengthOf(headings, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(headings[0].innerText, "title 3");
+```
+
+When the value of `#markdown-input` is `### title 3`, an `h3` element with the text of `title 3` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "### title 3";
+input.dispatchEvent(new Event("input"));
+const headings = preview.querySelectorAll("h3");
+assert.lengthOf(headings, 1);
+assert.lengthOf(preview.children, 1);
+assert.equal(headings[0].innerText, "title 3");
+```
+
+When the value of `#markdown-input` is `some text ### title 3`, `convertMarkdown()` should not convert `### title 3` into an `h3` element.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "some text ### title 3";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const testH3 = testDiv.querySelector("h3")
+assert.notExists(testH3);
+```
+
+When the value of `#markdown-input` is `**this is bold**`, `convertMarkdown()` should return `this is bold`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "**this is bold**";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const strongs = testDiv.querySelectorAll("strong");
+assert.lengthOf(strongs, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(strongs[0].innerText, "this is bold");
+```
+
+When the value of `#markdown-input` is `**this is bold**`, `this is bold` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "**this is bold**";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const strongs = testDiv.querySelectorAll("strong");
+assert.lengthOf(strongs, 1);
+assert.lengthOf(testDiv.children, 1)
+assert.equal(strongs[0].innerText, "this is bold");
+```
+
+When the value of `#markdown-input` is `**this is bold**`, a `strong` element with the text of `this is bold` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "**this is bold**";
+input.dispatchEvent(new Event("input"));
+const strongs = preview.querySelectorAll("strong");
+assert.lengthOf(strongs, 1);
+assert.lengthOf(preview.children, 1)
+assert.equal(strongs[0].innerText, "this is bold");
+```
+
+When the value of `#markdown-input` is `__this is bold__`, `convertMarkdown()` should return `this is bold`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "__this is bold__";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const strongs = testDiv.querySelectorAll("strong");
+assert.lengthOf(strongs, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(strongs[0].innerText, "this is bold");
+```
+
+When the value of `#markdown-input` is `__this is bold__`, `this is bold` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "__this is bold__";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const strongs = testDiv.querySelectorAll("strong");
+assert.lengthOf(strongs, 1);
+assert.lengthOf(testDiv.children, 1)
+assert.equal(strongs[0].innerText, "this is bold");
+```
+
+When the value of `#markdown-input` is `__this is bold__`, a `strong` element with the text of `this is bold` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "__this is bold__";
+input.dispatchEvent(new Event("input"));
+const strongs = preview.querySelectorAll("strong");
+assert.lengthOf(strongs, 1);
+assert.lengthOf(preview.children, 1)
+assert.equal(strongs[0].innerText, "this is bold");
+```
+
+When the value of `#markdown-input` is `*this is italic*`, `convertMarkdown()` should return `this is italic`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "*this is italic*";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const italics = testDiv.querySelectorAll("em");
+assert.lengthOf(italics, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(italics[0].innerText, "this is italic");
+```
+
+When the value of `#markdown-input` is `*this is italic*`, `this is italic` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "*this is italic*";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const italics = testDiv.querySelectorAll("em");
+assert.lengthOf(italics, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(italics[0].innerText, "this is italic");
+```
+
+When the value of `#markdown-input` is `*this is italic*`, an `em` element with the text of `this is italic` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "*this is italic*";
+input.dispatchEvent(new Event("input"));
+const italics = preview.querySelectorAll("em");
+assert.lengthOf(italics, 1);
+assert.lengthOf(preview.children, 1);
+assert.equal(italics[0].innerText, "this is italic");
+```
+
+When the value of `#markdown-input` is `_this is italic_`, `convertMarkdown()` should return `this is italic`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "_this is italic_";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const italics = testDiv.querySelectorAll("em");
+assert.lengthOf(italics, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(italics[0].innerText, "this is italic");
+```
+
+When the value of `#markdown-input` is `_this is italic_`, `this is italic` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "_this is italic_";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const italics = testDiv.querySelectorAll("em");
+assert.lengthOf(italics, 1);
+assert.lengthOf(testDiv.children, 1);
+assert.equal(italics[0].innerText, "this is italic");
+```
+
+When the value of `#markdown-input` is `_this is italic_`, an `em` element with the text of `this is italic` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "_this is italic_";
+input.dispatchEvent(new Event("input"));
+const italics = preview.querySelectorAll("em");
+assert.lengthOf(italics, 1);
+assert.lengthOf(preview.children, 1);
+assert.equal(italics[0].innerText, "this is italic");
+```
+
+When the value of `#markdown-input` is either `# **title 1**` or `# __title 1__`, `convertMarkdown()` should return `
` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "# **title 1**";
+input.dispatchEvent(new Event("input"));
+const testDiv1 = document.createElement("div");
+testDiv1.innerHTML = output.innerText;
+let headings = testDiv1.querySelectorAll("h1")
+let testStrong = testDiv1.querySelector("h1>strong")
+assert.lengthOf(testDiv1.children, 1);
+assert.lengthOf(headings, 1);
+assert.lengthOf(headings[0].children, 1);
+assert.exists(testStrong);
+assert.equal(testStrong.innerText, "title 1");
+
+input.value = "# __title 1__";
+input.dispatchEvent(new Event("input"));
+const testDiv2 = document.createElement("div");
+testDiv2.innerHTML = output.innerText;
+headings = testDiv2.querySelectorAll("h1")
+testStrong = testDiv2.querySelector("h1>strong")
+assert.lengthOf(testDiv2.children, 1);
+assert.lengthOf(headings, 1);
+assert.lengthOf(headings[0].children, 1);
+assert.exists(testStrong);
+assert.equal(testStrong.innerText, "title 1");
+```
+
+When the value of `#markdown-input` is either `# **title 1**` or `# __title 1__`, you set the inner HTML of `#preview` to `
title 1
`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "# **title 1**";
+input.dispatchEvent(new Event("input"));
+let headings = preview.querySelectorAll("h1")
+let testStrong = preview.querySelector("h1>strong")
+assert.lengthOf(preview.children, 1);
+assert.lengthOf(headings, 1);
+assert.lengthOf(headings[0].children, 1);
+assert.exists(testStrong);
+assert.equal(testStrong.innerText, "title 1");
+
+input.value = "# __title 1__";
+input.dispatchEvent(new Event("input"));
+headings = preview.querySelectorAll("h1")
+testStrong = preview.querySelector("h1>strong")
+assert.lengthOf(preview.children, 1);
+assert.lengthOf(headings, 1);
+assert.lengthOf(headings[0].children, 1);
+assert.exists(testStrong);
+assert.equal(testStrong.innerText, "title 1");
+```
+
+When the value of `#markdown-input` is ``, `convertMarkdown()` should return ``.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const imgs = testDiv.querySelectorAll("img");
+assert.lengthOf(testDiv.children, 1);
+assert.lengthOf(imgs, 1);
+assert.equal(imgs[0].alt, "alt-text");
+assert.isTrue(imgs[0].src.endsWith("image-source"));
+```
+
+When the value of `#markdown-input` is ``, `` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const imgs = testDiv.querySelectorAll("img");
+assert.lengthOf(testDiv.children, 1)
+assert.lengthOf(imgs, 1);
+assert.equal(imgs[0].alt, "alt-text");
+assert.isTrue(imgs[0].src.endsWith("image-source"));
+```
+
+When the value of `#markdown-input` is ``, `` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "";
+input.dispatchEvent(new Event("input"));
+const imgs = preview.querySelectorAll("img");
+assert.lengthOf(preview.children, 1)
+assert.lengthOf(imgs, 1);
+assert.equal(imgs[0].alt, "alt-text");
+assert.isTrue(imgs[0].src.endsWith("image-source"));
+```
+
+When the value of `#markdown-input` is `[link text](URL)`, `convertMarkdown()` should return `link text`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "[link text](URL)";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const anchors = testDiv.querySelectorAll("a");
+assert.lengthOf(testDiv.children, 1);
+assert.lengthOf(anchors, 1);
+assert.isTrue(anchors[0].href.endsWith("URL"));
+assert.equal(anchors[0].innerText, "link text");
+```
+
+When the value of `#markdown-input` is `[link text](URL)`, `link text` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "[link text](URL)";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const anchors = testDiv.querySelectorAll("a");
+assert.lengthOf(testDiv.children, 1);
+assert.lengthOf(anchors, 1);
+assert.isTrue(anchors[0].href.endsWith("URL"));
+assert.equal(anchors[0].innerText, "link text");
+```
+
+When the value of `#markdown-input` is `[link text](URL)`, `link text` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "[link text](URL)";
+input.dispatchEvent(new Event("input"));
+const anchors = preview.querySelectorAll("a");
+assert.lengthOf(preview.children, 1);
+assert.lengthOf(anchors, 1);
+assert.isTrue(anchors[0].href.endsWith("URL"));
+assert.equal(anchors[0].innerText, "link text");
+```
+
+When the value of `#markdown-input` is `> this is a quote`, `convertMarkdown()` should return `
this is a quote
`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "> this is a quote";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const quotes = testDiv.querySelectorAll("blockquote");
+assert.lengthOf(testDiv.children, 1);
+assert.lengthOf(quotes, 1);
+assert.equal(quotes[0].innerText, "this is a quote");
+```
+
+When the value of `#markdown-input` is `> this is a quote`, `
this is a quote
` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "> this is a quote";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const quotes = testDiv.querySelectorAll("blockquote");
+assert.lengthOf(testDiv.children, 1);
+assert.lengthOf(quotes, 1);
+assert.equal(quotes[0].innerText, "this is a quote");
+```
+
+When the value of `#markdown-input` is `> this is a quote`, `
this is a quote
` should be appended as a child of `#preview`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "> this is a quote";
+input.dispatchEvent(new Event("input"));
+const quotes = preview.querySelectorAll("blockquote");
+assert.lengthOf(preview.children, 1);
+assert.lengthOf(quotes, 1);
+assert.equal(quotes[0].innerText, "this is a quote");
+```
+
+When the value of `#markdown-input` is `some text > not a quote anymore`, `convertMarkdown()` should not convert `> not a quote anymore` into a `blockquote` element.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "some text > not a quote anymore";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const testQuote = testDiv.querySelector("blockquote")
+assert.notExists(testQuote);
+```
+
+When the value of `#markdown-input` is `> **this is a *quote***`, `convertMarkdown()` should return `
this is a quote
`.
+
+```js
+const input = document.querySelector("#markdown-input");
+input.value = "> **this is a *quote***";
+const testDiv = document.createElement("div");
+testDiv.innerHTML = convertMarkdown();
+const quotes = testDiv.querySelectorAll("blockquote");
+const strongs = testDiv.querySelectorAll("blockquote>strong");
+const italics = testDiv.querySelectorAll("blockquote>strong>em");
+assert.lengthOf(testDiv.children, 1);
+assert.lengthOf(quotes, 1);
+assert.lengthOf(quotes[0].children, 1);
+assert.lengthOf(strongs, 1);
+assert.lengthOf(strongs[0].children, 1);
+assert.equal(strongs[0].innerText, "this is a quote");
+assert.lengthOf(italics, 1);
+assert.equal(italics[0].innerText, "quote");
+```
+
+When the value of `#markdown-input` is `> **this is a *quote***`, `
this is a quote
` should be displayed inside `#html-output`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const output = document.querySelector("#html-output");
+input.value = "> **this is a *quote***";
+input.dispatchEvent(new Event("input"));
+const testDiv = document.createElement("div");
+testDiv.innerHTML = output.innerText;
+const quotes = testDiv.querySelectorAll("blockquote");
+const strongs = testDiv.querySelectorAll("blockquote>strong");
+const italics = testDiv.querySelectorAll("blockquote>strong>em");
+assert.lengthOf(testDiv.children, 1);
+assert.lengthOf(quotes, 1);
+assert.lengthOf(quotes[0].children, 1);
+assert.lengthOf(strongs, 1);
+assert.lengthOf(strongs[0].children, 1);
+assert.equal(strongs[0].innerText, "this is a quote");
+assert.lengthOf(italics, 1);
+assert.equal(italics[0].innerText, "quote");
+```
+
+When the value of `#markdown-input` is `> **this is a *quote***`, you should set the inner HTML of `#preview` to `
this is a quote
`.
+
+```js
+const input = document.querySelector("#markdown-input");
+const preview = document.querySelector("#preview");
+input.value = "> **this is a *quote***";
+input.dispatchEvent(new Event("input"));
+const quotes = preview.querySelectorAll("blockquote");
+const strongs = preview.querySelectorAll("blockquote>strong");
+const italics = preview.querySelectorAll("blockquote>strong>em");
+assert.lengthOf(preview.children, 1);
+assert.lengthOf(quotes, 1);
+assert.lengthOf(quotes[0].children, 1);
+assert.lengthOf(strongs, 1);
+assert.lengthOf(strongs[0].children, 1);
+assert.equal(strongs[0].innerText, "this is a quote");
+assert.lengthOf(italics, 1);
+assert.equal(italics[0].innerText, "quote");
+```
+
+You should have only one `script` element in your HTML.
+
+```js
+assert.lengthOf(document.querySelectorAll("script"), 3);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Markdown to HTML Converter
+
+
+
+
+