+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdebe67ec0f25a4798356.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdebe67ec0f25a4798356.md
new file mode 100644
index 00000000000..e030b927fe8
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdebe67ec0f25a4798356.md
@@ -0,0 +1,178 @@
+---
+id: 641cdebe67ec0f25a4798356
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+If the `messageInput` is empty, display an alert to the user with the message `Please enter a message.`.
+
+Then, exit the function execution.
+
+# --hints--
+
+Your callback function should have an `if` statement.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(/)
+```
+
+Your `if` statement should check if the `value` of `messageInput` is an empty string.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)/)
+```
+
+Your `if` statement should display an alert to the user with the message `Please enter a message.`.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)\s*\{\s*alert\(\s*('|"|`)Please enter a message\.\3\s*\)/)
+```
+
+Your `if` statement should exit the function execution.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)\s*\{\s*alert\(\s*('|"|`)Please enter a message\.\3\s*\);?\s*return\s*;?\s*\}\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+--fcc-editable-region--
+checkMessageButton.addEventListener("click", () => {
+
+});
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdefa704f232675ed98aa.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdefa704f232675ed98aa.md
new file mode 100644
index 00000000000..a4040bef0ab
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdefa704f232675ed98aa.md
@@ -0,0 +1,181 @@
+---
+id: 641cdefa704f232675ed98aa
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+Create an `isSpam` function using the `const` keyword and arrow syntax. The function should take a single parameter `msg` and implicitly return `false` for now.
+
+# --hints--
+
+You should use `const` to delcare an `isSpam` variable.
+
+```js
+assert.match(code, /const\s+isSpam\s*=/);
+```
+
+You should use arrow syntax to assign `isSpam` a function.
+
+```js
+assert.match(code, /const\s+isSpam\s*=\s*\(?.*\)?\s*=>/);
+```
+
+Your `isSpam` function should have a single `msg` parameter.
+
+```js
+assert.match(code, /const\s+isSpam\s*=\s*\(?\s*msg\s*\)?/);
+```
+
+Your `isSpam` function should implicitly return `false`.
+
+```js
+assert.match(code, /const\s+isSpam\s*=\s*\(?\s*msg\s*\)?\s*=>\s*false;?/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdf57c3f7ee276e1d9b32.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdf57c3f7ee276e1d9b32.md
new file mode 100644
index 00000000000..b27545ea927
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cdf57c3f7ee276e1d9b32.md
@@ -0,0 +1,199 @@
+---
+id: 641cdf57c3f7ee276e1d9b32
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+Back in your event listener, you need to update the text of the `result` element.
+
+Use a ternary operator to update the text of the `result` element after the `if` statement. Check the truthiness of calling `isSpam()` on the value of the `messageInput` element. If true, set the text to `Oh no! This looks like a spam message.`. Otherwise, set the text to `This message does not seem to contain any spam.`
+
+Then set the `messageInput` element's value to an empty string.
+
+# --hints--
+
+You should use the assignment operator to set the `textContent` property of the `result` element.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)\s*\{\s*alert\(\s*('|"|`)Please enter a message\.\3\s*\);?\s*return\s*;?\s*\}\s*result\.textContent\s*\=\s*/)
+```
+
+You should assign the `isSpam()` function call to `result.textContent`.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)\s*\{\s*alert\(\s*('|"|`)Please enter a message\.\3\s*\);?\s*return\s*;?\s*\}\s*result\.textContent\s*\=\s*isSpam\(\s*messageInput\.value\s*\)/)
+```
+
+You should use ternary syntax to check the truthiness of `isSpam(messageInput.value)`.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)\s*\{\s*alert\(\s*('|"|`)Please enter a message\.\3\s*\);?\s*return\s*;?\s*\}\s*result\.textContent\s*\=\s*isSpam\(\s*messageInput\.value\s*\)\s*\?/)
+```
+
+The truthy expression of your ternary should set the `textContent` property of the `result` element to `Oh no! This looks like a spam message.`.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)\s*\{\s*alert\(\s*('|"|`)Please enter a message\.\3\s*\);?\s*return\s*;?\s*\}\s*result\.textContent\s*\=\s*isSpam\(\s*messageInput\.value\s*\)\s*\?\s*('|"|`)Oh no! This looks like a spam message.\4\s*:/);
+```
+
+The falsy expression of your ternary should set the `textContent` property of the `result` element to `This message does not seem to contain any spam.`.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)\s*\{\s*alert\(\s*('|"|`)Please enter a message\.\3\s*\);?\s*return\s*;?\s*\}\s*result\.textContent\s*\=\s*isSpam\(\s*messageInput\.value\s*\)\s*\?\s*('|"|`)Oh no! This looks like a spam message.\4\s*:\s*('|"|`)This message does not seem to contain any spam.\5;?\s*/);
+```
+
+After your ternary, set the `value` of `messageInput` to an empty string.
+
+```js
+assert.match(code, /checkMessageButton\.addEventListener\(\s*('|"|`)click\1\s*,\s*\(\s*\)\s*=>\s*\{\s*if\s*\(\s*messageInput\.value\s*===\s*('|"|`)\2\s*\)\s*\{\s*alert\(\s*('|"|`)Please enter a message\.\3\s*\);?\s*return\s*;?\s*\}\s*result\.textContent\s*\=\s*isSpam\(\s*messageInput\.value\s*\)\s*\?\s*('|"|`)Oh no! This looks like a spam message.\4\s*:\s*('|"|`)This message does not seem to contain any spam.\5;?\s*messageInput\.value\s*=\s*('|"|`)\6;?\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const isSpam = (msg) => false;
+
+--fcc-editable-region--
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+
+});
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce03dfeca10293e05dad7.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce03dfeca10293e05dad7.md
new file mode 100644
index 00000000000..4b9ba9bc1af
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce03dfeca10293e05dad7.md
@@ -0,0 +1,188 @@
+---
+id: 641ce03dfeca10293e05dad7
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+Your first regular expression will be used to catch help requests. Declare a `helpRegex` variable, and assign it a regular expression that matches the string `please help`.
+
+As a refresher, here is a regular expression to match the string `hello world`:
+
+```js
+const regex = /hello world/;
+```
+
+# --hints--
+
+You should use `const` to declare a `helpRegex` variable.
+
+```js
+assert.match(code, /const\s+helpRegex\s*=/);
+```
+
+Your `helpRegex` variable should be a regular expression.
+
+```js
+assert.instanceOf(helpRegex, RegExp);
+```
+
+Your `helpRegex` variable should match the string `please help`.
+
+```js
+assert.match('please help', helpRegex);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+const isSpam = (msg) => false;
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce3065c50e62f97406973.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce3065c50e62f97406973.md
new file mode 100644
index 00000000000..c0028fec254
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce3065c50e62f97406973.md
@@ -0,0 +1,172 @@
+---
+id: 641ce3065c50e62f97406973
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Regular expressions can take flags to modify their behavior. For instance, the `i` flag can be used to make the expression ignore case, causing it to match `hello`, `HELLO`, and `Hello` for the expression `/hello/`.
+
+Flags are added after the trailing backslash. Add the `i` flag to your `helpRegex`.
+
+# --hints--
+
+Your `helpRegex` should have the case-insensitive `i` flag.
+
+```js
+assert.include(helpRegex.flags, 'i');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+--fcc-editable-region--
+const helpRegex = /please help/;
+--fcc-editable-region--
+
+const isSpam = (msg) => false;
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce3dcd0aec8309fbc9971.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce3dcd0aec8309fbc9971.md
new file mode 100644
index 00000000000..aa5f5c1bb48
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ce3dcd0aec8309fbc9971.md
@@ -0,0 +1,174 @@
+---
+id: 641ce3dcd0aec8309fbc9971
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Strings have a `.match()` method, which accepts a regular expression as an argument and determines if the string matches that expression.
+
+Update your `isSpam()` function to implicitly return the result of calling the `.match()` method on `msg`, passing `helpRegex` as the argument.
+
+Then, try entering some messages on your page and see the result.
+
+# --hints--
+
+Your `isSpam()` function should implicitly return the result of `msg.match(helpRegex)`.
+
+```js
+assert.match(code, /const\s*isSpam\s*=\s*\(msg\)\s*=>\s*msg\.match\(helpRegex\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help/i;
+
+--fcc-editable-region--
+const isSpam = (msg) => false;
+--fcc-editable-region--
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ceed81533263283835c3d.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ceed81533263283835c3d.md
new file mode 100644
index 00000000000..318d7db7662
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641ceed81533263283835c3d.md
@@ -0,0 +1,174 @@
+---
+id: 641ceed81533263283835c3d
+title: Step 9
+challengeType: 0
+dashedName: step-9
+---
+
+# --description--
+
+Instead of using the `.match()` method, you can use the `.test()` method of a regular expression to test if a string matches the pattern. Unlike `.match()`, `.test()` returns a boolean value indicating whether or not the string matches the pattern.
+
+Update your `isSpam()` function to use the `.test()` method of `helpRegex` to test if `msg` is a match.
+
+Then, try entering some messages on your page and see the result.
+
+# --hints--
+
+Your `isSpam()` function should implicitly return the result of `helpRegex.test(msg)`.
+
+```js
+assert.match(code, /const\s*isSpam\s*=\s*\(msg\)\s*=>\s*helpRegex\.test\(msg\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help/i;
+
+--fcc-editable-region--
+const isSpam = (msg) => msg.match(helpRegex);
+--fcc-editable-region--
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cf198ec366c33d6504854.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cf198ec366c33d6504854.md
new file mode 100644
index 00000000000..db22a7b6b2f
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/641cf198ec366c33d6504854.md
@@ -0,0 +1,184 @@
+---
+id: 641cf198ec366c33d6504854
+title: Step 10
+challengeType: 0
+dashedName: step-10
+---
+
+# --description--
+
+The alternate sequence `|` can be used to match either the text on the left or the text on the right of the `|`. For example, the regular expression `/yes|no/` will match either `yes` or `no`.
+
+Update your `helpRegex` to match either `please help` or `assist me`.
+
+# --hints--
+
+Your `helpRegex` should use the `|` alternate sequence.
+
+```js
+assert.match(helpRegex.toString(), /\|/);
+```
+
+Your `helpRegex` should match the string `please help`.
+
+```js
+assert.match('please help', helpRegex);
+```
+
+Your `helpRegex` should match the string `assist me`.
+
+```js
+assert.match('assist me', helpRegex);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+--fcc-editable-region--
+const helpRegex = /please help/i;
+--fcc-editable-region--
+
+const isSpam = (msg) => helpRegex.test(msg);
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/6421f6f59d665615c9e94d8a.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/6421f6f59d665615c9e94d8a.md
new file mode 100644
index 00000000000..bfbdaa2e30b
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/6421f6f59d665615c9e94d8a.md
@@ -0,0 +1,186 @@
+---
+id: 6421f6f59d665615c9e94d8a
+title: Step 11
+challengeType: 0
+dashedName: step-11
+---
+
+# --description--
+
+Before you start creating additional regular expressions, you need to update your application to check more than one regular expression.
+
+Start by declaring a `denyList` variable. Assign it an array containing your `helpRegex`.
+
+# --hints--
+
+You should use `const` to declare a `denyList` variable.
+
+```js
+assert.match(code, /const\s*denyList\s*=/);
+```
+
+Your `denyList` variable should be an array.
+
+```js
+assert.isArray(denyList);
+```
+
+Your `denyList` array should have `helpRegex` as its only element.
+
+```js
+assert.deepEqual(denyList, [helpRegex]);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+const isSpam = (msg) => helpRegex.test(msg);
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/6421f98f4999d1179ce37cb4.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/6421f98f4999d1179ce37cb4.md
new file mode 100644
index 00000000000..0d884ee0ab3
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/6421f98f4999d1179ce37cb4.md
@@ -0,0 +1,192 @@
+---
+id: 6421f98f4999d1179ce37cb4
+title: Step 12
+challengeType: 0
+dashedName: step-12
+---
+
+# --description--
+
+Remember that arrays have a `.some()` method. Use the `.some()` method to check if testing your `msg` on any of your `denyList` regular expressions returns `true`.
+
+Use `regex` as the parameter for the callback function, for clarity.
+
+# --hints--
+
+Your `isSpam` function should implicitly return the result of `denyList.some()`.
+
+```js
+assert.match(code, /const\s*isSpam\s*=\s*\(?\s*msg\s*\)?\s*=>\s*/)
+```
+
+Your `.some()` method should use arrow syntax for the callback.
+
+```js
+assert.match(code, /const\s*isSpam\s*=\s*\(?\s*msg\s*\)?\s*=>\s*denyList\.some\(\s*\(?.*\)?\s*=>/);
+```
+
+Your `.some()` callback should take `regex` as the parameter.
+
+```js
+assert.match(code, /const\s*isSpam\s*=\s*\(?\s*msg\s*\)?\s*=>\s*denyList\.some\(\s*\(?\s*regex\s*\)?\s*=>/);
+```
+
+Your `.some()` callback should implicitly return the result of testing `msg` on `regex`.
+
+```js
+assert.match(code, /const\s*isSpam\s*=\s*\(?\s*msg\s*\)?\s*=>\s*denyList\.some\(\s*\(?\s*regex\s*\)?\s*=>\s*regex\.test\(\s*msg\s*\)\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+
+const denyList = [helpRegex];
+
+--fcc-editable-region--
+const isSpam = (msg) => helpRegex.test(msg);
+--fcc-editable-region--
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642205fa6376c818f78bb24e.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642205fa6376c818f78bb24e.md
new file mode 100644
index 00000000000..38360e8284d
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642205fa6376c818f78bb24e.md
@@ -0,0 +1,193 @@
+---
+id: 642205fa6376c818f78bb24e
+title: Step 13
+challengeType: 0
+dashedName: step-13
+---
+
+# --description--
+
+The next regular expression you will work on is one that matches mentions of dollar amounts.
+
+Start by declaring a `dollarRegex` variable, and assign it a case-insensitive regular expression that matches the text `dollars`.
+
+# --hints--
+
+You should use `const` to declare a `dollarRegex` variable.
+
+```js
+assert.match(code, /const\s*dollarRegex\s*=/);
+```
+
+Your `dollarRegex` variable should be a regular expression.
+
+```js
+assert.instanceOf(dollarRegex, RegExp);
+```
+
+Your `dollarRegex` should match `dollars`.
+
+```js
+assert.match('dollars', dollarRegex);
+```
+
+Your `dollarRegex` should be case-insensitive.
+
+```js
+assert.include(dollarRegex.flags, 'i');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+const dollarRegex = /dollars/i;
+
+--fcc-editable-region--
+const denyList = [helpRegex];
+--fcc-editable-region--
+
+const isSpam = (msg) => denyList.some((regex) => regex.test(msg));
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642206e054eef81b5e3092ed.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642206e054eef81b5e3092ed.md
new file mode 100644
index 00000000000..f879e8ee96d
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642206e054eef81b5e3092ed.md
@@ -0,0 +1,189 @@
+---
+id: 642206e054eef81b5e3092ed
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+You need to match a number before the text `dollars`. While you could write out `0|1|2` and so on, regular expressions have a feature that makes this easier.
+
+A character class is defined by square brackets, and matches any character within the brackets. For example, `[aeiou]` matches any character in the list `aeiou`. You can also define a range of characters to match using a hyphen. For example, `[a-z]` matches any character from `a` to `z`.
+
+Add a character class to match the digits `0` through `9` to your `dollarRegex` expression - remember the digit must come before the word `dollars`, and there should be a space between the digit and the word.
+
+# --hints--
+
+Your `dollarRegex` should use a character class.
+
+```js
+assert.match(dollarRegex.source, /\[.*\]/);
+```
+
+Your character class should be `0-9`.
+
+```js
+assert.match(dollarRegex.source, /\[0-9\]/);
+```
+
+Your `dollarRegex` should match `1 dollars`.
+
+```js
+assert.match('1 dollars', dollarRegex);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+--fcc-editable-region--
+const dollarRegex = /dollars/i;
+--fcc-editable-region--
+
+const denyList = [helpRegex, dollarRegex];
+
+const isSpam = (msg) => denyList.some((regex) => regex.test(msg));
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642208bc4d44701c6fd6f65e.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642208bc4d44701c6fd6f65e.md
new file mode 100644
index 00000000000..6cadb0b8709
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642208bc4d44701c6fd6f65e.md
@@ -0,0 +1,193 @@
+---
+id: 642208bc4d44701c6fd6f65e
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+The dollar value may be more than one digit. To match this, the `+` quantifier can be used - this matches one or more consecutive occurrence. For example, the regular expression `/a+/` matches one or more consecutive `a` characters.
+
+Update your regular expression to match one or more consecutive digits.
+
+# --hints--
+
+Your `dollarRegex` should use the `+` quantifier.
+
+```js
+assert.match(dollarRegex.source, /\+/);
+```
+
+Your `dollarRegex` should use the `+` quantifier on your `[0-9]` character class.
+
+```js
+assert.match(dollarRegex.source, /\[0-9\]\+/);
+```
+
+Your `dollarRegex` should match `100 dollars`.
+
+```js
+assert.match('100 dollars', dollarRegex);
+```
+
+Your `dollarRegex` should match `3 dollars`.
+
+```js
+assert.match('3 dollars', dollarRegex);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+--fcc-editable-region--
+const dollarRegex = /[0-9] dollars/i;
+--fcc-editable-region--
+
+const denyList = [helpRegex, dollarRegex];
+
+const isSpam = (msg) => denyList.some((regex) => regex.test(msg));
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220e8cb589f61e625bf453.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220e8cb589f61e625bf453.md
new file mode 100644
index 00000000000..9b6e7192541
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220e8cb589f61e625bf453.md
@@ -0,0 +1,215 @@
+---
+id: 64220e8cb589f61e625bf453
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Between your digits and your `dollars` text, you want to catch place values.
+
+Use the `|` token to allow `hundred`, `thousand`, `million`, or `billion` between your digits and `dollars`.
+
+# --hints--
+
+Your `dollarRegex` should use the `|` token.
+
+```js
+assert.match(dollarRegex.source, /\|/);
+```
+
+Your `dollarRegex` should have three `|` tokens.
+
+```js
+assert.lengthOf(dollarRegex.source.match(/\|/g), 3);
+```
+
+Your `dollarRegex` should use the `|` token to match `hundred`, `thousand`, `million`, or `billion`.
+
+```js
+const placeValues = dollarRegex.source.replace("[0-9]+ ", "").replace(" dollars", "").split('|');
+assert.include(placeValues, 'hundred');
+assert.include(placeValues, 'thousand');
+assert.include(placeValues, 'million');
+assert.include(placeValues, 'billion');
+```
+
+Your `dollarRegex` should match `1 hundred dollars`.
+
+```js
+assert.match('1 hundred dollars', dollarRegex);
+```
+
+Your `dollarRegex` should match `1 thousand dollars`.
+
+```js
+assert.match('1 thousand dollars', dollarRegex);
+```
+
+Your `dollarRegex` should match `1 million dollars`.
+
+```js
+assert.match('1 million dollars', dollarRegex);
+```
+
+Your `dollarRegex` should match `1 billion dollars`.
+
+```js
+assert.match('1 billion dollars', dollarRegex);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+--fcc-editable-region--
+const dollarRegex = /[0-9]+ dollars/i;
+--fcc-editable-region--
+
+const denyList = [helpRegex, dollarRegex];
+
+const isSpam = (msg) => denyList.some((regex) => regex.test(msg));
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220f22dff8151f751a53a7.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220f22dff8151f751a53a7.md
new file mode 100644
index 00000000000..d06112d99fc
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220f22dff8151f751a53a7.md
@@ -0,0 +1,187 @@
+---
+id: 64220f22dff8151f751a53a7
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+A capture group is a way to define a part of the expression that should be captured and saved for later reference. You can define a capture group by wrapping a part of your expression in parentheses. For example, `/h(i|ey) camper/` would match either `hi camper` or `hey camper`, and would capture `i` or `ey` in a group.
+
+Turn your place values into a capture group.
+
+# --hints--
+
+You should not change your `helpRegex` regular expression.
+
+```js
+assert.match(helpRegex.source, /please help|assist me/);
+```
+
+Your `dollarRegex` should use a capture group.
+
+```js
+assert.match(dollarRegex.source, /\(.*\)/)
+```
+
+Your `hundred|thousand|million|billion` pattern should be a capture group.
+
+```js
+assert.match(dollarRegex.source, /\(hundred\|thousand\|million\|billion\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+--fcc-editable-region--
+const dollarRegex = /[0-9]+ hundred|thousand|million|billion dollars/i;
+--fcc-editable-region--
+
+const denyList = [helpRegex, dollarRegex];
+
+const isSpam = (msg) => denyList.some((regex) => regex.test(msg));
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220fb017c57d20612de8b8.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220fb017c57d20612de8b8.md
new file mode 100644
index 00000000000..3af8f66ca54
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64220fb017c57d20612de8b8.md
@@ -0,0 +1,181 @@
+---
+id: 64220fb017c57d20612de8b8
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Now that you have your capture group, you can mark the entire pattern as an optional match. The `?` quantifier matches zero or one occurrence of the preceding character or group. For example, the regular expression `/colou?r/` matches both `color` and `colour`, because the `u` is optional.
+
+Mark your capture group as optional.
+
+# --hints--
+
+Your `dollarRegex` should use the `?` quantifier.
+
+```js
+assert.match(dollarRegex.source, /\?/);
+```
+
+Your `(hundred|thousand|million|billion)` capture group should be optional.
+
+```js
+assert.match(dollarRegex.source, /\(hundred\|thousand\|million\|billion\)\?/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+--fcc-editable-region--
+const dollarRegex = /[0-9]+ (hundred|thousand|million|billion) dollars/i;
+--fcc-editable-region--
+
+const denyList = [helpRegex, dollarRegex];
+
+const isSpam = (msg) => denyList.some((regex) => regex.test(msg));
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64221007887f38213fa57827.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64221007887f38213fa57827.md
new file mode 100644
index 00000000000..b1c681fe077
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/64221007887f38213fa57827.md
@@ -0,0 +1,195 @@
+---
+id: 64221007887f38213fa57827
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+One last thing with this expression. You don't actually need the match value from your capture group, so you can turn it into a non-capturing group. This will allow you to group the characters together without preserving the result.
+
+To create a non-capturing group in a regular expression, you can add `?:` after the opening parenthesis of a group. For instance, `(?:a|b)` will match either `a` or `b`, but it will not capture the result.
+
+Update your regular expression to use a non-capturing group.
+
+# --hints--
+
+Your `dollarRegex` should use `?:`.
+
+```js
+assert.match(dollarRegex.source, /\?:/);
+```
+
+Your `dollarRegex` should use a non-capturing group.
+
+```js
+assert.match(dollarRegex.source, /\(\?:.*\)/);
+```
+
+Your `(hundred|thousand|million|billion)` should be a non-capturing group.
+
+```js
+assert.match(dollarRegex.source, /\(\?:hundred\|thousand\|million\|billion\)/);
+```
+
+Your `(hundred|thousand|million|billion)` group should still be optional.
+
+```js
+assert.match(dollarRegex.source, /\(\?:hundred\|thousand\|million\|billion\)\?/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --dark-grey: #1b1b32;
+ --light-grey: #f5f6f7;
+ --golden-yellow: #fecc4c;
+ --yellow: #ffcc4c;
+ --gold: #feac32;
+ --orange: #ffac33;
+ --dark-orange: #f89808;
+}
+
+body {
+ background-color: var(--dark-grey);
+ color: var(--light-grey);
+}
+
+body,
+#message-input:placeholder-shown {
+ text-align: center;
+}
+
+textarea {
+ max-width: 90%;
+}
+
+.main-text {
+ margin: 25px 0;
+}
+
+.title {
+ font-size: 2.5rem;
+}
+
+.description {
+ margin-top: 15px;
+ font-size: 1.4rem;
+}
+
+.message-label {
+ display: block;
+ margin-bottom: 20px;
+ font-size: 1.5rem;
+}
+
+#message-input:placeholder-shown,
+textarea {
+ font-size: 1.1rem;
+}
+
+.btn {
+ display: block;
+ cursor: pointer;
+ width: 200px;
+ margin: 10px auto;
+ color: var(--dark-grey);
+ background-color: var(--gold);
+ background-image: linear-gradient(var(--golden-yellow), var(--orange));
+ border-color: var(--gold);
+ border-width: 3px;
+}
+
+.btn:hover {
+ background-image: linear-gradient(var(--yellow), var(--dark-orange));
+}
+
+#result {
+ font-size: 2rem;
+ margin: 20px 0;
+}
+
+.footer {
+ margin-top: 10px;
+}
+```
+
+```js
+const messageInput = document.getElementById("message-input");
+const result = document.getElementById("result");
+const checkMessageButton = document.getElementById("check-message-btn");
+
+const helpRegex = /please help|assist me/i;
+--fcc-editable-region--
+const dollarRegex = /[0-9]+ (hundred|thousand|million|billion)? dollars/i;
+--fcc-editable-region--
+
+const denyList = [helpRegex, dollarRegex];
+
+const isSpam = (msg) => denyList.some((regex) => regex.test(msg));
+
+checkMessageButton.addEventListener("click", () => {
+ if (messageInput.value === "") {
+ alert("Please enter a message.");
+ return;
+ }
+
+ result.textContent = isSpam(messageInput.value)
+ ? "Oh no! This looks like a spam message."
+ : "This message does not seem to contain any spam.";
+ messageInput.value = "";
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642213bf8d38b0227ed6ab0b.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642213bf8d38b0227ed6ab0b.md
new file mode 100644
index 00000000000..ffff341569f
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-regular-expressions-by-building-a-spam-filter/642213bf8d38b0227ed6ab0b.md
@@ -0,0 +1,192 @@
+---
+id: 642213bf8d38b0227ed6ab0b
+title: Step 21
+challengeType: 0
+dashedName: step-21
+---
+
+# --description--
+
+Your next regular expression will look for strings like `free money`. Start by declaring a `freeRegex` variable and assigning it a regular expression that will match the string `free money`. Remember to make it case-insensitive.
+
+# --hints--
+
+You should declare a `freeRegex` variable using `const`.
+
+```js
+assert.match(code, /const\s*freeRegex\s*=/);
+```
+
+Your `freeRegex` variable should be a regular expression.
+
+```js
+assert.instanceOf(freeRegex, RegExp);
+```
+
+Your `freeRegex` should match `free money`.
+
+```js
+assert.match('free money', freeRegex);
+```
+
+Your `freeRegex` should be case-insensitive.
+
+```js
+assert.include(freeRegex.flags, 'i');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ Learn Regular Expressions by Building a Spam Filter
+
+
+
+
+
+
Is this Spam?
+
+ Enter a phrase to check if it would be marked as spam or not.
+