freeCodeCamp 课程挑战文件实战解析:用 hr 元素在卡片中创建水平分割线
【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp
本文以 freeCodeCamp 开源课程库中的经典 HTML/CSS 挑战《Create a Horizontal Line Using the hr Element》为核心,完整解读挑战文档的字段与结构约定、种子代码(seed)与标准答案的构造方法,以及如何通过断言测试验证<hr>水平分割线的正确插入位置。读完后你将掌握该课程挑战文件的 Markdown 分节规范、void 元素<hr>的实际应用场景,以及前后挑战如何围绕同一张卡片递进演进的编写思路。
挑战在课程中的位置
该挑战文件位于英文课程目录下的 Applied Visual Design(应用视觉设计)模块:
- 挑战文件:curriculum/challenges/english/blocks/applied-visual-design/587d781b367417b2b2512abb.md
- 模块结构定义:curriculum/structure/blocks/applied-visual-design.json
从 applied-visual-design.json 的challengeOrder数组可以看到,该挑战(id 为587d781b367417b2b2512abb)被安排在“Use the s Tag to Strikethrough Text”(删除线)之后、“Adjust the background-color Property of Text”(调整背景色)之前,模块的helpCategory标注为HTML-CSS。整个模块由若干短小的挑战按序编排,共同围绕同一张“个人资料卡片”逐步搭建:前面的挑战为卡片的h4标题加入删除线文字,本挑战为标题与正文之间加一条水平线,后面的挑战再修改h4的背景色与内边距。这种“一张卡片逐步成型”的编排方式,是本模块最核心的教学设计。
挑战文档的结构规范
freeCodeCamp 的每个挑战都是一个带 YAML front matter 的 Markdown 文件,通过#一级标题分隔出若干固定分节。本挑战文件的完整骨架如下:
--- id: 587d781b367417b2b2512abb title: Create a Horizontal Line Using the hr Element challengeType: 0 videoUrl: '...' forumTopicId: 301049 dashedName: create-a-horizontal-line-using-the-hr-element --- # --description-- 知识点讲解 # --instructions-- 给学员的具体任务指令 # --hints-- 分步提示,每条提示附对应测试断言 # --seed-- ## --seed-contents-- 学员打开编辑器时的初始代码 # --solutions-- 参考解答front matter 各字段的作用:
| 字段 | 本挑战取值 | 说明 |
|---|---|---|
id | 587d781b367417b2b2512abb | 挑战唯一标识(MongoDB ObjectId),结构文件中的challengeOrder即按此 id 排序 |
title | Create a Horizontal Line Using the hr Element | 挑战标题 |
challengeType | 0 | 挑战类型,用于区分经典编辑器挑战与测验等其他类型(类型定义见 packages/shared/src/config/challenge-types.ts) |
videoUrl | 外部视频教程地址 | 可选的教学视频 |
forumTopicId | 301049 | 关联的官方论坛主题编号 |
dashedName | create-a-horizontal-line-using-the-hr-element | 挑战的稳定 slug,用于生成/learn/路由路径 |
挑战字段与分节的合法性由课程 schema 校验,相关校验逻辑位于 curriculum/schema/challenge-schema.js,其中使用 Joi 定义了fileJoi(含seed、contents等代码文件字段)、prerequisitesJoi等对象结构,课程构建时会依据 curriculum/package.json 中的测试流程对挑战文件做校验,保证每个挑战的结构完整、可被编辑器正确加载。
核心知识点:hr 是用于视觉分组的水平分割线
本挑战的--description--分节给出了<hr>元素的标准定义:
你可以使用
hr标签在其包含元素的宽度范围内绘制一条水平线。它可以用来表示话题的切换,或者在视觉上分隔不同组的内容。
结合--instructions--分节的补充说明,需要掌握两个要点:
- 用途:
<hr>表达的是“主题/内容分组的边界”这一语义,而不是单纯的装饰。在本挑战中,它恰好把卡片的标题区(h4)与介绍区(p)划分成两个视觉区块。 - void 元素:在 HTML 中
<hr>是 void element(空元素),不需要单独的闭合标签,写<hr>即可,写成<hr/>也合法。这也是后文测试断言要同时兼容两种写法的原因。
种子代码(seed)解析
--seed-contents--分节中给出了学员打开编辑器时的完整初始代码。它是一张已具备样式的卡片:
<style> h4 { text-align: center; height: 25px; } p { text-align: justify; } .links { text-align: left; color: black; } .fullCard { width: 245px; border: 1px solid #ccc; border-radius: 5px; margin: 10px 5px; padding: 4px; } .cardContent { padding: 10px; } .cardText { margin-bottom: 30px; } </style> <div class="fullCard"> <div class="cardContent"> <div class="cardText"> <h4><s>Google</s>Alphabet</h4> <p><em>Google was founded by Larry Page and Sergey Brin while they were <u>Ph.D. students</u> at <strong>Stanford University</strong>.</em></p> </div> <div class="cardLinks"> <a href="https://en.wikipedia.org/wiki/Larry_Page" target="_blank" class="links">Larry Page</a><br><br> <a href="https://en.wikipedia.org/wiki/Sergey_Brin" target="_blank" class="links">Sergey Brin</a> </div> </div> </div>几个值得注意的衔接细节:
<h4>中的<s>Google</s>Alphabet正是上一挑战(587d781b367417b2b2512aba.md,“Use the s Tag to Strikethrough Text”)的作答结果被固化成了本挑战的 seed,直观体现了模块的递进关系;- 任务指令要求把
<hr>加在“包含卡片标题的h4下方”,从 seed 结构看,也就是在</h4>与<p>之间(seed 中该行恰好留有一个空行作为提示位); p内的em、u、strong标签同样来自前序挑战(斜体、下划线、加粗)的作答,cardLinks区则属于后续挑战(hover 状态、链接字号等)的改造对象。
标准答案与最小改动
--solutions--分节给出的参考解答与 seed 相比只有一行差异——在h4与p之间插入<hr>:
<div class="fullCard"> <div class="cardContent"> <div class="cardText"> <h4><s>Google</s>Alphabet</h4> <hr> <p><em>Google was founded by Larry Page and Sergey Brin while they were <u>Ph.D. students</u> at <strong>Stanford University</strong>.</em></p> </div> <div class="cardLinks"> <a href="https://en.wikipedia.org/wiki/Larry_Page" target="_blank" class="links">Larry Page</a><br><br> <a href="https://en.wikipedia.org/wiki/Sergey_Brin" target="_blank" class="links">Sergey Brin</a> </div> </div> </div>样式部分(<style>块)与 seed 完全一致,说明本挑战考察的只是语义元素的插入位置,不要求任何 CSS 改动。<hr>作为块级元素,会自动横跨其包含元素.cardText的内容宽度,配合.cardText的margin-bottom: 30px,标题与正文之间形成清晰的视觉隔断。
测试断言解析:测试如何验证 hr 的正确性
--hints--分节中的每条提示都附带一条可执行的断言,它们也是平台判定挑战通过的最终依据:
断言一:页面中恰好存在一个hr
assert.lengthOf(document.querySelectorAll('hr'),1);通过 DOM API 统计<hr>数量,确认学员确实在标记中添加了水平线,且没有多余元素。
断言二:hr必须位于标题与段落之间
assert.match(code,/<\/h4>\s*?<hr(>|\s*?\/>)\s*?<p>/gi);这条正则直接匹配源代码文本,拆解如下:
| 片段 | 含义 |
|---|---|
<\/h4> | 以标题结束标签为定位起点 |
\s*? | 允许中间存在任意空白(懒匹配) |
<hr(>|\s*?\/>) | 兼容<hr>与<hr/>两种 void 写法 |
\s*?<p> | 紧随其后必须出现段落开始标签 |
gi标志使其不区分大小写并可全局匹配。两条断言合起来即完整表达了任务要求:“在标记中添加一个hr,且它必须夹在标题和段落之间”——与--instructions--的文字描述一一对应。
小结:从一张挑战文件看课程编写范式
这篇挑战文件虽然内容简短,却完整覆盖了 freeCodeCamp 挑战编写的全部要素:front matter 元数据(id、dashedName、forumTopicId)、--description--中的知识点陈述、--instructions--的可执行任务、带断言的--hints--分步提示、可直接运行的--seed-contents--,以及最小 diff 的--solutions--。再结合 applied-visual-design.json 的排序与前后挑战(删除线挑战、背景色挑战)对同一张卡片的持续改造,可以看到该课程模块通过“小步递进、断言兜底”的方式,让<hr>这类基础 HTML 语义元素在具体项目语境中被反复巩固——这也是学习该仓库课程编写规范时值得参考的典型样例。
【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考