feat(curriculum): add extra space capturing (#55841)

Co-authored-by: Krzysztof G. <60067306+gikf@users.noreply.github.com>
Co-authored-by: Naomi the Technomancer <accounts+github@nhcarrigan.com>
This commit is contained in:
Anna
2024-08-19 16:16:50 -04:00
committed by GitHub
parent 3cbafc160c
commit ab17e9d2fd
18 changed files with 255 additions and 66 deletions

View File

@@ -85,68 +85,72 @@
"title": "Step 19"
},
{
"id": "64221007887f38213fa57827",
"id": "66bb6467b4b7381178420970",
"title": "Step 20"
},
{
"id": "642213bf8d38b0227ed6ab0b",
"id": "64221007887f38213fa57827",
"title": "Step 21"
},
{
"id": "64233060735ddf06451c5c8c",
"id": "642213bf8d38b0227ed6ab0b",
"title": "Step 22"
},
{
"id": "64233094a1293c079b5b0996",
"id": "64233060735ddf06451c5c8c",
"title": "Step 23"
},
{
"id": "6423322e71f8d108608005cb",
"id": "64233094a1293c079b5b0996",
"title": "Step 24"
},
{
"id": "6423331f0527840934183aba",
"id": "6423322e71f8d108608005cb",
"title": "Step 25"
},
{
"id": "642335220b7d830a69eb59fb",
"id": "6423331f0527840934183aba",
"title": "Step 26"
},
{
"id": "642335d232d7690b2d67dbaf",
"id": "642335220b7d830a69eb59fb",
"title": "Step 27"
},
{
"id": "64233d08f234a310e73f9496",
"id": "642335d232d7690b2d67dbaf",
"title": "Step 28"
},
{
"id": "642344dc9390c712080432c7",
"id": "64233d08f234a310e73f9496",
"title": "Step 29"
},
{
"id": "64234598ef08dd13114edae5",
"id": "642344dc9390c712080432c7",
"title": "Step 30"
},
{
"id": "6423462975f33b14056583de",
"id": "64234598ef08dd13114edae5",
"title": "Step 31"
},
{
"id": "6423472aeed932150e8984b6",
"id": "6423462975f33b14056583de",
"title": "Step 32"
},
{
"id": "64234797d84734163088961a",
"id": "6423472aeed932150e8984b6",
"title": "Step 33"
},
{
"id": "6423491485db5e1786dd6434",
"id": "64234797d84734163088961a",
"title": "Step 34"
},
{
"id": "642349b5b7bae31af21cd5f8",
"id": "6423491485db5e1786dd6434",
"title": "Step 35"
},
{
"id": "642349b5b7bae31af21cd5f8",
"title": "Step 36"
}
]
}
}

View File

@@ -1,8 +1,8 @@
---
id: 64221007887f38213fa57827
title: Step 20
title: Step 21
challengeType: 0
dashedName: step-20
dashedName: step-21
---
# --description--
@@ -174,7 +174,7 @@ 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;
const dollarRegex = /[0-9]+\s*(hundred|thousand|million|billion)?\s+dollars/i;
--fcc-editable-region--
const denyList = [helpRegex, dollarRegex];

View File

@@ -1,8 +1,8 @@
---
id: 642213bf8d38b0227ed6ab0b
title: Step 21
title: Step 22
challengeType: 0
dashedName: step-21
dashedName: step-22
---
# --description--
@@ -169,7 +169,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
--fcc-editable-region--
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 64233060735ddf06451c5c8c
title: Step 22
title: Step 23
challengeType: 0
dashedName: step-22
dashedName: step-23
---
# --description--
@@ -163,7 +163,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /free money/i;
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 64233094a1293c079b5b0996
title: Step 23
title: Step 24
challengeType: 0
dashedName: step-23
dashedName: step-24
---
# --description--
@@ -177,7 +177,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
--fcc-editable-region--
const freeRegex = /free money/i;
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 6423322e71f8d108608005cb
title: Step 24
title: Step 25
challengeType: 0
dashedName: step-24
dashedName: step-25
---
# --description--
@@ -163,7 +163,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
--fcc-editable-region--
const freeRegex = /fr[e3][e3] mon[e3]y/i;
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 6423331f0527840934183aba
title: Step 25
title: Step 26
challengeType: 0
dashedName: step-25
dashedName: step-26
---
# --description--
@@ -160,7 +160,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
--fcc-editable-region--
const freeRegex = /fr[e3][e3] m[o0]n[e3]y/i;
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 642335220b7d830a69eb59fb
title: Step 26
title: Step 27
challengeType: 0
dashedName: step-26
dashedName: step-27
---
# --description--
@@ -179,7 +179,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
--fcc-editable-region--
const freeRegex = /\sfr[e3][e3] m[o0]n[e3]y\s/i;
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 642335d232d7690b2d67dbaf
title: Step 27
title: Step 28
challengeType: 0
dashedName: step-27
dashedName: step-28
---
# --description--
@@ -197,7 +197,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
--fcc-editable-region--
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y\s/i;
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 64233d08f234a310e73f9496
title: Step 28
title: Step 29
challengeType: 0
dashedName: step-28
dashedName: step-29
---
# --description--
@@ -195,7 +195,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 642344dc9390c712080432c7
title: Step 29
title: Step 30
challengeType: 0
dashedName: step-29
dashedName: step-30
---
# --description--
@@ -169,7 +169,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
--fcc-editable-region--
const stockRegex = /stock alert/i;

View File

@@ -1,8 +1,8 @@
---
id: 64234598ef08dd13114edae5
title: Step 30
title: Step 31
challengeType: 0
dashedName: step-30
dashedName: step-31
---
# --description--
@@ -169,7 +169,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
--fcc-editable-region--
const stockRegex = /st[o0]ck al[e3]rt/i;

View File

@@ -1,8 +1,8 @@
---
id: 6423462975f33b14056583de
title: Step 31
title: Step 32
challengeType: 0
dashedName: step-31
dashedName: step-32
---
# --description--
@@ -175,7 +175,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
--fcc-editable-region--
const stockRegex = /[s5][t7][o0]ck al[e3]r[t7]/i;

View File

@@ -1,8 +1,8 @@
---
id: 6423472aeed932150e8984b6
title: Step 32
title: Step 33
challengeType: 0
dashedName: step-32
dashedName: step-33
---
# --description--
@@ -175,7 +175,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
--fcc-editable-region--
const stockRegex = /[s5][t7][o0]ck [a@4]l[e3]r[t7]/i;

View File

@@ -1,8 +1,8 @@
---
id: 64234797d84734163088961a
title: Step 33
title: Step 34
challengeType: 0
dashedName: step-33
dashedName: step-34
---
# --description--
@@ -205,7 +205,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
--fcc-editable-region--
const stockRegex = /[s5][t7][o0][c{[(]k [a@4]l[e3]r[t7]/i;

View File

@@ -1,8 +1,8 @@
---
id: 6423491485db5e1786dd6434
title: Step 34
title: Step 35
challengeType: 0
dashedName: step-34
dashedName: step-35
---
# --description--
@@ -199,7 +199,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
const stockRegex = /(?:^|\s)[s5][t7][o0][c{[(]k [a@4]l[e3]r[t7](?:$|\s)/i;
--fcc-editable-region--

View File

@@ -1,8 +1,8 @@
---
id: 642349b5b7bae31af21cd5f8
title: Step 35
title: Step 36
challengeType: 0
dashedName: step-35
dashedName: step-36
---
# --description--
@@ -237,7 +237,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
const stockRegex = /(?:^|\s)[s5][t7][o0][c{[(]k [a@4]l[e3]r[t7](?:$|\s)/i;
--fcc-editable-region--
@@ -393,7 +393,7 @@ const result = document.getElementById("result");
const checkMessageButton = document.getElementById("check-message-btn");
const helpRegex = /please help|assist me/i;
const dollarRegex = /[0-9]+ (?:hundred|thousand|million|billion)? dollars/i;
const dollarRegex = /[0-9]+\s*(?:hundred|thousand|million|billion)?\s+dollars/i;
const freeRegex = /(?:^|\s)fr[e3][e3] m[o0]n[e3]y(?:$|\s)/i;
const stockRegex = /(?:^|\s)[s5][t7][o0][c{[(]k [a@4]l[e3]r[t7](?:$|\s)/i;
const dearRegex = /(?:^|\s)d[e3][a@4]r fr[i1|][e3]nd(?:$|\s)/i;

View File

@@ -0,0 +1,185 @@
---
id: 66bb6467b4b7381178420970
title: Step 20
challengeType: 0
dashedName: step-20
---
# --description--
While this expression does match `1 hundred dollars`, it will not match `1 hundred dollars`, or `10 dollars`.
Spam messages can and will find a way to exploit flaws in your detection. Time to improve your regex.
Replace the first literal space with the `\s*` expression. The `\s` character class matches whitespace, such as spaces, tabs, and new lines. The `*` quantifier means "match the previous character 0 or more times".
Replace the second literal space with `\s+`. The `+` quantifier means "match the previous character at least one time".
# --hints--
Your `dollarRegex` must not use literal spaces.
```js
assert.notMatch(dollarRegex.source, / /);
```
Your `dollarRegex` must allow any number of spaces before the dollar quantity, and one or more spaces after.
```js
assert.match(dollarRegex.source, /\\s\*\(hundred\|thousand\|million\|billion\)\?\\s\+/);
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Learn Regular Expressions by Building a Spam Filter</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<header class="main-text">
<h1 class="title">Is this Spam?</h1>
<p class="description">
Enter a phrase to check if it would be marked as spam or not.
</p>
</header>
<main>
<label class="message-label" for="message-input">Message: </label>
<textarea
placeholder="Enter message here"
value=""
type="text"
name="message"
id="message-input"
rows="10"
cols="40"
></textarea>
<button class="btn" id="check-message-btn" type="button">
Check message
</button>
<p id="result"></p>
</main>
<footer class="footer">&copy; freeCodeCamp</footer>
<script src="./script.js"></script>
</body>
</html>
```
```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 = "";
});
```