为 free-programming-books 贡献免费编程资源:收录标准、Markdown 条目规范与 CI 自动校验完全指南
导读
free-programming-books 是一个以纯 Markdown 数据文件维护“可免费获取的编程学习资源”清单的大型开源项目,其核心不是代码,而是一套高度纪律化的内容贡献规范。本文以仓库内的权威指南 docs/CONTRIBUTING.md 为主线,完整解析其收录标准、六类资源清单的划分、Markdown 条目格式、元数据约定、RTL/LTR 双向文本处理,以及由 GitHub Actions 驱动的自动化质量门禁(格式 lint 与 URL 校验)。读完本文,你将能够按照与仓库维护者完全一致的标准提交链接、编写符合规范的清单条目,并读懂并修复 CI 报出的各类 lint 错误,从而写出一次通过校验的 Pull Request。
全文事实均取自本仓库内的指南文档、工作流定义与 linter 脚本源码,文中给出的仓库相对路径可点击继续阅读原始证据。
贡献前须知:协议、行为准则与两条参与路径
Contributor License Agreement 与行为准则
任何贡献者都需要先接受仓库的两项基础约定(见 docs/CONTRIBUTING.md):
- 贡献者许可协议(CLA):贡献内容等同于同意仓库根目录的 LICENSE(CC BY 许可);
- 贡献者行为准则(Code of Conduct):贡献行为需遵守 docs/CODE_OF_CONDUCT.md,该准则有大量语言译本,完整索引见 docs/README.md#translations。
不懂 Git 也没关系:两条路径任选
核心原则是“先查重,再提交”:如果你找到的是仓库中尚未收录的免费资源:
- 不会用 Git:直接在仓库的 Issues 中提出新链接的建议即可;
- 熟悉 Git:Fork 仓库并提交 Pull Request(PR)。
无论走哪条路,最终内容都会进入同一套人工评审与自动化校验流程(见下文“自动化质量门禁”),这也是仓库将 Issue 设为新手友好入口的原因。
六类资源清单:先选对清单再动手
贡献的第一步是判断资源到底属于哪一种清单。仓库把学习资源分为 6 类(见 docs/CONTRIBUTING.md),分类错误是 PR 最常见的返工原因:
| 类型 | 判定要点 | 仓库对应数据文件 |
|---|---|---|
| Books(书籍) | PDF、HTML、ePub、基于 gitbook.io 的站点、Git 仓库等 | books/free-programming-books-langs.md、books/free-programming-books-subjects.md 及各语言文件 books/free-programming-books-*.md |
| Courses(课程) | 非书籍形态的学习材料,如 MIT OCW 的“算法导论”课程 | courses/free-courses-en.md 及各语言 courses/free-courses-*.md |
| Interactive Tutorials(交互式教程) | 让用户输入代码/命令并实时求值的交互网站(“求值”≠“打分”),如 Try Haskell、Try Git 一类 | more/free-programming-interactive-tutorials-en.md 等 |
| Playgrounds(编程游乐场) | 在线交互网站、游戏或桌面软件:可写代码、编译/运行并分享代码片段,常支持 fork 动手试玩 | more/free-programming-playgrounds.md |
| Podcasts and Screencasts(播客与录屏) | 播客与屏幕录制教学 | casts/free-podcasts-screencasts-en.md 及各语言 casts/free-podcasts-screencasts-*.md |
| Problem Sets & Competitive Programming(题目集与竞赛编程) | 通过解决难易不等的问题来评测编程技能的网站/软件,可选代码评审与横向比较 | more/problem-sets-competitive-programming.md |
仓库佐证:CI 中的 fpb-lint 工作流 正是对这四大目录执行扫描:
fpb-lint books casts courses more;RTL/LTR 双向文本 linter 同样扫描books casts courses more四个目录(见 rtl-ltr-linter 工作流)。这说明六类清单在物理上分属books/、courses/、casts/、more/四个顶层目录。
额外分类提示
- 中文与英文:英文书籍被拆分为“按编程语言(By Programming Language)”与“按主题(By Subject)”两个主文件;通用主题书籍归入主题清单的
Programming小节,其余按各自子类展开(见 books/free-programming-books-langs.md 开篇说明)。 - 每个清单文件都以**字母序的 Index(目录)**开头,列出全部
###小节与####子节的锚点链接。
链接收录指南:什么样的链接可以进清单
这一节是文档中约束最密集的部分,覆盖“是否免费”与“链接质量”两类判断(见 docs/CONTRIBUTING.md):
免费的边界
- “能轻易下载到书”不等于“免费书”,只收录免费内容,请务必反复确认;
- 不收录要求提供可用邮箱才能取书的页面;但允许收录“请求邮箱(非强制)”的条目,并要在括号中加语言合适的注释,例如
(email address *requested*, not required); - 不接受托管在 Google Drive、Dropbox、Mega、Scribd、Issuu 及其他类似文件上传平台的链接;
- 若是旧书,建议在标题中附带出版年份;作者处也应署名(详见“元数据约定”一节)。
链接来源与 URL 形态
| 规则 | 说明 | 示例 |
|---|---|---|
| 权威来源优先 | 作者官网 > 出版社官网 > 第三方网站 | 优先链接到作者本人站点 |
| 禁止文件托管平台 | 不限于 Dropbox、Google Drive | —— |
| https 优先 | 同域名、同内容时,https 优于 http |
—— |
| 根域名去掉尾斜杠 | http://example.com 优于 http://example.com/ |
—— |
| 取最短链接 | http://example.com/dir/ 优于 http://example.com/dir/index.html |
—— |
| 禁用短链服务 | 不接受任何 URL shortener | —— |
| “当前版”优先于“版本号” | .../book/current/ 优于 .../book/v1.0.0/index.html |
—— |
| 移除跟踪码 | 链接中的 tracking codes 必须清除 | —— |
| 国际化 URL 转义 | 需对非 ASCII URL 做转义处理 | —— |
| 链接须直指资源本身 | 不接受指向“别的页面”而非所列资源的 URL | —— |
证书/SSL 问题的三级处理
如果链接存在过期证书、自签名证书或任何 SSL 问题,按以下顺序处置:
- 若能找到对应的
http版本则替换之(移动端处理证书例外往往很麻烦); - 若没有 http 版本、但通过浏览器添加例外仍可访问,则保留该 https 链接;
- 否则删除该链接。
多格式、多版本与多出处
- 同一资源存在多种格式时,优先找一个入口即含多格式的单一链接;确无单一入口时,可为一个资源添加带格式注释的多个链接。每个链接都会带来维护负担,因此应尽量避免冗余;
- 同一资源在不同位置存在时,取权威来源;若属不同版本且差异足够大,则分别作为独立条目并注明各自版本;
- 条目若有“in process”“archived”“免费许可”等情况,使用下文规定的专有记号。
Git 提交习惯
- 偏好原子提交(一次提交对应一个条目的新增/删除/修改),但 PR 前不必强制 squash;
- 维护者不会强制此规则,它只是为了便于审阅。
Markdown 条目格式规范:可被 CI 机器校验的排版
所有清单都是 .md 文件,格式会被 CI 用程序强校验,因此格式即规范。以下规则全部来自 docs/CONTRIBUTING.md,逐条落实才能通过自动化检查。
结构性规则
- 每个清单文件顶部必须有 Index 目录,按字母序列出所有
###小节(含####子节); - 小节用
###(三级标题),子节用####(四级标题); - 空行规则(“空行数”指 Markdown 源文件中的空行):
- 2 个空行:最后一个链接 与 下一个新小节之间;
- 1 个空行:标题 与 本小节第一个链接之间;
- 0 个空行:两个链接之间;
- 1 个空行:每个
.md文件结尾必须留一个空行。
标准布局示例:
[...]
* [An Awesome Book](http://example.com/example.html)
### Example
* [Another Awesome Book](http://example.com/book.html)
* [Some Other Book](http://example.com/other.html)
行内语法规则
]与(之间不得有空格:
BAD : * [Another Awesome Book] (http://example.com/book.html)
GOOD: * [Another Awesome Book](http://example.com/book.html)
- 作者与链接之间用“空格-连字符-空格”(
-)分隔:
BAD : * [Another Awesome Book](http://example.com/book.html)- John Doe
GOOD: * [Another Awesome Book](http://example.com/book.html) - John Doe
- 格式说明与链接之间留一个空格,且作者在前、格式在后:
BAD : * [A Very Awesome Book](https://example.org/book.pdf)(PDF)
GOOD: * [A Very Awesome Book](https://example.org/book.pdf) (PDF)
BAD : * [A Very Awesome Book](https://example.org/book.pdf)- (PDF) Jane Roe
GOOD: * [A Very Awesome Book](https://example.org/book.pdf) - Jane Roe (PDF)
- 多格式:优先单链接;确需分开时,把次要格式以带说明的链接形式并到同一条目:
BAD : * [Another Awesome Book](http://example.com/)- John Doe (HTML)
BAD : * [Another Awesome Book](https://downloads.example.org/book.html)- John Doe (download site)
GOOD: * [Another Awesome Book](http://example.com/) - John Doe (HTML) [(PDF, EPUB)](https://downloads.example.org/book.html)
- 旧书的出版年份放进标题括号内,而不是行尾:
BAD : * [A Very Awesome Book](https://example.org/book.html) - Jane Roe - 1970
GOOD: * [A Very Awesome Book (1970)](https://example.org/book.html) - Jane Roe
- 未完稿书籍加
in process记号:
GOOD: * [Will Be An Awesome Book Soon](http://example.com/book2.html) - John Doe (HTML) *( :construction: in process)*
- 通过 Wayback Machine 等归档服务恢复的资源加
archived记号(应选用最近且完整的快照版本):
GOOD: * [A Way-backed Interesting Book](https://web.archive.org/web/<snapshot-id>/http://example.com/) - John Doe (HTML) *( :card_file_box: archived)*
免费许可标记(License Notes)
仓库鼓励收录采用免费开放许可(如 Creative Commons)的资源;标注格式统一为“格式之后、其他备注之前”的括号注释:
GOOD: * [A Very Awesome Book](https://example.org/book.pdf) - Jane Roe (PDF) (CC BY-SA)
支持的许可短码(不携带版本号):
| 短码 | 全称 |
|---|---|
CC BY |
Creative Commons attribution |
CC BY-NC |
Creative Commons non-commercial |
CC BY-SA |
Creative Commons share-alike |
CC BY-NC-SA |
Creative Commons non-commercial, share-alike |
CC BY-ND |
Creative Commons no-derivatives |
CC BY-NC-ND |
Creative Commons non-commercial, no-derivatives |
GFDL |
Gnu Free Documentation License |
添加许可注释的五步操作(来自 docs/CONTRIBUTING.md):
- 在资源页面确认许可——查看页脚、About 页或 LICENSE/Legal 区块;只标注“免费/开放内容许可”,不要写 “All Rights Reserved”;
- 将许可字符串归一化为上表短码且去掉版本号:例如 “Creative Commons Attribution 4.0” →
CC BY;“CC BY-SA 3.0” →CC BY-SA;“GNU Free Documentation License” →GFDL; - 将许可放在格式之后、其他备注之前:
- 单一格式:
* [A Very Awesome Book](https://example.org/book.pdf) - Jane Roe (PDF) (CC BY-SA) - 多格式:
* [Awesome Guide](https://example.org/) - Jane Roe (HTML, PDF) (CC BY) - 带附加备注(如 archived / in process):
* Old but Gold - John Doe (HTML) (CC BY) *( :card_file_box: archived)*
- 单一格式:
- 若不同版本/格式的许可不同,请拆成独立条目并各自标注正确许可;
- 不确定时,在 PR 中留言说明你认为该资源采用自由许可的依据与出处。
字母序规则:清单的排序基准
各小节内链接必须按字母序排列(见 docs/CONTRIBUTING.md):
- 首字母相同则继续比较第二、第三个字符,依次类推:
aa排在ab之前; - 空格参与比较:
one two排在onetwo之前(空格比字符小); - 若发现错位链接,直接查看 lint 报错信息,它会告诉你哪两行需要互换。
元数据与细节约定
清单只维护最小元数据集合:标题、URL、创作者、平台与访问说明(见 docs/CONTRIBUTING.md)。每一项都有细化约定:
Titles(标题)
- 不发明标题:标题取自资源自身,贡献者不得为编辑目的自拟标题;历史价值明显的旧作可在标题后加括号年份;
- 禁止全大写:默认用 title case,不确定时沿用资源原始大小写;
- 禁止 emoji。
URLs
- 禁止短链;必须移除跟踪码;国际化 URL 需转义;
- 实现 https 的站点一律用
https; - URL 必须直指资源本体,不欢迎“跳到别处”的页面。
Creators(创作者署名)
- 适当署上创作者姓名,译者也要署名;
- 译作应同时署名原作者,推荐用 MARC relators 术语标注非作者角色的贡献,如译者为
trl.::
* [A Translated Book](http://example.com/book.html) - John Doe, `trl.:` Mike The Translator
- 作者列表用逗号分隔;过长名单可用 “
et al.” 缩写; - 创作者不允许外链;编者型作品需加说明,如 GoalKicker/RIP Tutorial 类应写作 “
Compiled from StackOverflow documentation”; - 姓名不带 “Prof.”、“Dr.” 等敬称。
有时限的课程与试用(Time-limited Courses and Trials)
- 不收录“六个月内就需要删除”的内容;
- 有报名时段限制或明确持续期的课程不收录;
- “限时免费”资源不收录。
平台与访问说明(Platforms and Access Notes)
- 课程清单中平台是资源描述的重要部分:不同平台有不同的访问模型与设施。虽然通常不收录需要注册的书籍,但许多课程平台(如 Coursera、EdX、Udacity、Udemy)没有账号就无法使用其核心设施,因此课程依赖平台时,应在括号内列出平台名;
- YouTube:不把 YouTube 本身列为平台,而是尽量列创作者(它往往是子平台);一般不链接单个 YouTube 视频,除非时长超过一小时且结构上像课程/教程——此时务必在 PR 描述中说明;
- 禁止
youtu.be/xxxx类短链; - Leanpub:访问模型混杂(有的免注册可读、有的需 Leanpub 账号免费阅读)。鉴于其书目质量与访问模型流动性,允许收录后者,但需加访问说明
*(Leanpub account or valid email requested)*。
边界判定:什么该收、什么不该收
“资源该进哪张清单”的第一条判断法则是看资源如何自我描述——它自称 book,那多半就该进书籍清单。以下是仓库明确不收录的类型(见 docs/CONTRIBUTING.md):
- 博客、博客文章、文章;
- 普通网站(托管“海量被收录条目”的站点除外);
- 非课程/录屏形式的视频、书籍章节、书的试读样章;
- IRC/Telegram 频道、Slack 群组与邮件列表。
竞赛编程类清单对上述排除项的执行尺度相对宽松;范围调整属于社区议题,建议通过 Issue 提出。仓库的收录边界最终由社区共同决定(见 docs/CONTRIBUTING.md)。
Books vs. Courses vs. Interactive Tutorials
- 书感信号:有 ISBN、有目录、提供可下载版本(尤其 ePub)、有版本迭代、不依赖交互或视频、尽量全面自洽地覆盖主题。具备越多越像书,但也有大量收录条目并不齐备,须结合语境判断;
- 课程:通常附带教材(教材本身归书籍清单);课程应有讲座、练习、测验、笔记或教辅,单条讲座视频或单份 PowerPoint 不是课程;
- 交互式教程的硬判据非常直白:“如果打印出来仍不失其精髓,那它就不是交互式教程”。
自动化质量门禁:贡献如何被机器校验
贡献指南明确告知:GitHub Actions 会在每次 PR 运行测试,确保清单按字母序排列并遵守格式规范(见 docs/CONTRIBUTING.md)。仓库内部实际部署了三道闸门:
1. 格式与排序 lint:fpb-lint
仓库通过 GitHub Actions 运行 free-programming-books-lint(fpb-lint)检查所有数据文件的排序与排版。fpb-lint 工作流 中的真实执行命令为:
- run: npm install -g free-programming-books-lint
- name: Run linter
run: |
fpb-lint books casts courses more &> output.log
它把完整报错写入 output.log 并作为 PR artifact 上传,维护者与贡献者都可直接下载查看;前文“错位链接看 lint 报错”正是依赖这一闸门。
2. URL 有效性校验:check_urls
URL 校验由 awesome_bot 驱动。触发方式是:推送一条提交信息中包含 check_urls=待检文件 的 commit,例如:
check_urls=free-programming-books.md free-programming-books-en.md
- 可以同时指定多个文件,用单个空格分隔;
- 注意陷阱:校验多个文件时,构建结果以最后被检查的文件为准,因此可能看到“绿灯通过”的假象——提交者务必在 PR 底部的 “Show all checks” → “Details” 中查看构建日志末尾,确认每个文件都真实通过。
3. RTL/LTR 双向文本 lint(仅 RTL 语言文件)
仓库内置了独立的 Python 双向文本检查器 scripts/rtl_ltr_linter.py,其配置项集中在 scripts/rtl_ltr_linter_config.yml。对应工作流 .github/workflows/rtl-ltr-linter.yml 中安装依赖并执行的命令为:
pip install python-bidi PyYAML
python3 scripts/rtl_ltr_linter.py books casts courses more ${CHANGED_FILES_ARGS} --log-file rtl-linter-output.log
从源码结构看(scripts/rtl_ltr_linter.py),脚本先加载 YAML 配置中的默认值再与文件合并,支持按严重级别(error/warning/notice)分类输出,并会跳过代码块、行内代码与括号内容。判定是否属于 RTL 文件靠的是文件后缀规则(-ar/-he/-fa/-ur,见 scripts/rtl_ltr_linter.py),这也与指南所述“对 *-ar.md、*-he.md、*-fa.md、*-ur.md 文件运行”一致。工作流仅在 PR 带 RTL 标签或改动文件命中上述语言时触发(见 .github/workflows/rtl-ltr-linter.yml)。
修复 RTL/LTR 排版错误:两个记号 与
当清单混合了从右向左(RTL,如阿拉伯语、希伯来语、波斯语、乌尔都语)与从左向右(LTR,如英语、代码、技术名词)文本时,双向算法(Bidi)可能让浏览器渲染出与逻辑顺序不符的混乱排版。此时应使用 HTML 实体标记修正(见 docs/CONTRIBUTING.md):
- RTL 语境中的 LTR 单词(如 “HTML”、“JavaScript”):在每个 LTR 片段后紧跟
‏; - RTL 语境中的 LTR 符号(如 “C#”、“C++”):在每个 LTR 符号后紧跟
‎。
例 1:LTR 单词收尾的条目
BAD:
<div dir="rtl" markdown="1">
* كتاب الأمثلة في R - John Doe (PDF)
</div>
GOOD:
<div dir="rtl" markdown="1">
* كتاب الأمثلة في R‏ - John Doe‏ (PDF)
</div>
例 2:混合 RTL 作者列表中的 LTR 片段
BAD:
<div dir="rtl" markdown="1">
* Tech Podcast - بودكاست المثال – Ahmad Hasan, محمد علي
</div>
GOOD:
<div dir="rtl" markdown="1">
* Tech Podcast - بودكاست المثال – Ahmad Hasan,‏ محمد علي
</div>
例 3:LTR 符号(如 C#)需
BAD:
<div dir="rtl" markdown="1">
* أساسيات C#
</div>
GOOD:
<div dir="rtl" markdown="1">
* أساسيات C#‎
</div>
附带说明:这一规则同样可从配置得到印证——scripts/rtl_ltr_linter_config.yml 定义了约百个需要
‏的常见 LTR 关键词(HTML、JavaScript、Python、Docker、GraphQL等)与需要‎的 LTR 符号模式(C#、C++、.NET、Node.js、CI/CD等),并同时识别‏/‎及其‏/‎等 Unicode 数字实体写法。
给新贡献者的自检清单
综合 docs/CONTRIBUTING.md 全文,可在提交 PR 前逐项自查:
- 资源确实免费?未使用需要邮箱才能取书的页面;没有 Google Drive/Dropbox/Mega/Scribd/Issuu 类托管链接;
- 属于六类清单中的哪一类?文件放对目录了吗?
- 链接是否权威、最短、https、无尾斜杠、无短链、无跟踪码;
- 条目是否位于本小节正确字母序位置;Index 与锚点是否同步更新;
- 排版是否满足 2/1/0/1 空行规则、
]与(无空格、-分隔作者、作者在格式前、旧书年份放标题内; - 需要
in process、archived、(CC ...)或邮箱提示等记号时是否按规定书写; - RTL 语言文件是否已按本小节规则补齐
‏/‎; - 最后确认 GitHub Actions 的 lint/URL 检查在 PR 上全部通过(多文件 URL 校验时注意查看构建日志末尾而非只看绿灯)。
如果你想把这个项目克隆到本地按上述流程贡献,可使用仓库地址执行:
git clone https://gitcode.com/GitHub_Trending/fr/free-programming-books
延伸阅读:仓库内的相关证据文件
- 贡献指南原文(英文权威版):docs/CONTRIBUTING.md,多语言译本见 docs/README.md#translations(如中文版 docs/CONTRIBUTING-zh.md、繁体 docs/CONTRIBUTING-zh_TW.md);
- 新手 Git 操作指南:docs/HOWTO.md;行为准则:docs/CODE_OF_CONDUCT.md;
- 根级项目说明与资源入口:README.md(其中 README.md#how-to-contribute 一节也指向本指南);
- 数据清单示例:books/free-programming-books-langs.md、courses/free-courses-en.md、casts/free-podcasts-screencasts-en.md、more/free-programming-interactive-tutorials-en.md;
- CI 配置:.github/workflows/fpb-lint.yml、.github/workflows/check-urls.yml、.github/workflows/rtl-ltr-linter.yml;PR 模板见 .github/PULL_REQUEST_TEMPLATE.md;
- RTL/LTR linter 源码与配置:scripts/rtl_ltr_linter.py、scripts/rtl_ltr_linter_config.yml。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00