- 前端
- UI组件
【免费下载链接】bootstrap-sass
Official Sass port of Bootstrap 2 and 3.
bootstrap-sass 是 Bootstrap 3 的官方 Sass 移植版,它将上游以 LESS 编写的 Bootstrap 自动转换为 SCSS、JS 与字体资产。本文基于仓库 CONTRIBUTING.md 整理出完整的贡献流程:资产改动必须经过convertrake 任务校验、Bug 报告应如何定位归属与隔离问题、Pull Request 为何应修补转换器而非直接改 SCSS。读完本文,你将掌握 bootstrap-sass 的"转换器优先"协作模型,并了解如何提交可被维护者采纳的补丁。
一、贡献流程概览:转换器是资产改动的唯一入口
bootstrap-sass 与普通前端库的最大区别在于:仓库内的 SCSS、JavaScript 与字体资产都不是手写的,而是由一条自动化转换流水线从上游 twbs/bootstrap(LESS 源码)生成的。因此 CONTRIBUTING.md 开篇就立下两条硬性约定:
- 任何对
bootstrap-sass资产(scss、javascripts、fonts)的改动,都应先对照convertrake 任务的结果进行校验,使用说明见 README.md; - 如果转换器本身出了问题,优先修复转换器,连同资产一起更新,而不是绕过转换器直接手工修改生成产物。
这条规则的意义在于保持仓库的可再生性:只要上游 Bootstrap 发布新版本,维护者就能用同一套转换器重新生成全部资产。若有人手工改动了 SCSS,下一次convert就会把这些改动冲掉,造成无法追查的漂移。从源码结构看,这正是本仓库"SCSS 是编译产物而非源文件"这一架构决策的直接体现。
二、Asset Changes 的实操:如何运行convert任务
2.1 三种常用调用方式
convert任务定义在 Rakefile 中,接受一个可选的branch参数:
desc 'Convert bootstrap to bootstrap-sass' task :convert, :branch do |t, args| require './tasks/converter' Converter.new(branch: args[:branch]).process_bootstrap end对应的命令行用法:
# 拉取并转换上游 master 分支(默认) rake convert # 转换指定分支或提交哈希 rake convert[e8a1df5f060bf7e6631554648e0abde150aedbe4]第二条命令中,方括号是 Rake 向任务传递参数的标准写法,e8a1df5...是一个上游提交 SHA。传入的分支名或提交 SHA 会被Converter#initialize记录,用于确定要抓取的上游代码版本。
2.2 转换流水线内部做了什么
process_bootstrap(见 tasks/converter.rb)依次执行四步:
process_font_assets:把上游字体(.eot/.svg/.ttf/.woff/.woff2)复制到 assets/fonts/bootstrap;process_stylesheet_assets:把 LESS 逐个转换为 SCSS,落到 assets/stylesheets/bootstrap;process_javascript_assets:复制 JS 文件并生成 Sprockets manifest 与合并文件;store_version:把上游分支的最新提交 SHA 写回 lib/bootstrap-sass/version.rb 中的Bootstrap::BOOTSTRAP_SHA常量。
这四步正是 README.md "Upstream Converter" 一节描述的能力,也是评估"资产改动是否符合规范"的对照基准。
2.3 相关辅助任务
同文件还定义了其他配套任务:rake less_to_scss把 stdin 中的 LESS 直接转为 SCSS 输出到 stdout,适合单独调试某一段转换;rake compile用 SassC 把 SCSS 编译到tmp/目录;rake test(默认任务)运行 test 下全部*_test.rb测试。
三、转换器源码解析:LESS 到 Sass 的机械转换如何工作
convert任务的核心是 tasks/converter/less_conversion.rb,其注释明确说明:大多数差异通过正则与字符串替换修复,同时针对 Sass 3.2 缺少父选择器、递归、mixin 命名空间、@media内@extend等能力做了 Bootstrap 特化的 workaround。convert_to_scss方法(L160-L178)给出了一条完整的转换管线:
file = replace_vars(file) # @ 变量 -> $ 变量 file = replace_mixin_definitions(file) # .name() { -> @mixin name() { file = replace_mixins(file, mixins) # .mixin() -> @include mixin() / @extend file = extract_mixins_from_selectors(file, CLASSES_TO_MIXINS.inject({}) { |h, cl| h.update(".#{cl}" => cl) }) file = replace_spin(file) # spin() -> adjust-hue() file = replace_fadein(file) # fadein(a, b%) -> fade_in(a, b/100.0) file = replace_image_urls(file) # url() -> 资产辅助函数 file = replace_escaping(file) # ~"" 转义清理 file = convert_less_ampersand(file) # 处理 &- file = deinterpolate_vararg_mixins(file) file = replace_calculation_semantics(file) # 修复 a -b 的计算语义 file = replace_file_imports(file) # @import "x.less" -> @import "x"; file = wrap_at_groups_with_at_root(file) file = replace_division(file) # a / b -> math.div(a, b)几个值得展开的典型转换:
- 变量与 mixin 定义:
replace_vars用正则把非@mixin/@media/@page/@keyframes/@font-face上下文中的@替换为$;replace_mixin_definitions把.name(args) {改写成@mixin name(args) {。 - 调用点改写:
replace_mixins(L475-L499)把#scope > .mixin()转为@include scope-mixin(),把&:extend(.mixin all)转为@include mixin();若 mixin 名不在已收集的共享列表中则回退为@extend。 - 网格系统的递归展开:LESS 用递归定义网格列,Sass 支持真正的循环。
convert_grid_mixins与mixin_all_grid_columns(L233-L284)把递归改写为@for $i from ... through $grid-columns,并在产物中留下// [converter] This is defined recursively in LESS, but Sass supports real loops注释。 - 父选择器 workaround:
parameterize_mixin_parent_selector(L375-L391)为@mixin a($parent) { tr#{$parent} {...} }这类模式注入$parent参数;extract_nested_rule(L398-L415)把嵌套规则(如.x { textarea& {...} })提取为顶层textarea.x {...},转换时还会标注// [converter] extracted ...。 - 除法语义:
replace_division生成@use "sass:math";并把(a / b)改写为math.div(a, b),以适配现代 Sass 模块系统。
此外,process_stylesheet_assets(L60-L153)对个别文件做了特化修补:variables.less会插入$bootstrap-sass-asset-helper: false !default;与$icon-font-path的if()分支;dropdowns.less中把@extend .dropdown-menu-right;替换为right: 0; left: auto;;同时生成 templates/project/_bootstrap-variables.sass 供用户覆盖变量。转换完成后,主入口 assets/stylesheets/_bootstrap.scss 会调整 import 路径,把"bootstrap/..."前缀修正为全局可解析的形式。
四、转换器生态:JS、字体、网络缓存与扫描工具
转换器由多个模块拼装而成(见 tasks/converter.rb 的include列表),理解它们有助于在修复转换器时快速定位:
- tasks/converter/js_conversion.rb:复制上游 JS 到
assets/javascripts/bootstrap,并生成三类产物——assets/javascripts/bootstrap-sprockets.js(Sprockets 逐个 require 的 manifest)、assets/javascripts/bootstrap.js(合并全量)、assets/javascripts/bootstrap.min.js。其中bootstrap_js_files会对 tooltip/popover 排序,保证依赖顺序正确。 - tasks/converter/fonts_conversion.rb:按
.eot|svg|ttf|woff2?匹配并复制字体文件。 - tasks/converter/network.rb:通过 GitHub API 取分支 SHA 与文件树、并发下载 raw 文件,并把下载结果缓存到
tmp/converter-cache-bootstrap(目录名由Converter#initialize的cache_path参数决定),二次转换可复用缓存。 - tasks/converter/char_string_scanner.rb:基于
StringScanner的字符级扫描器,解决正则匹配的字节/字符偏移问题,是replace_rules、close_brace_pos等花括号配平算法的底层依赖。 - tasks/converter/logger.rb:把转换过程输出到 STDERR,用 ANSI 颜色区分"状态/处理中/已转换/HTTP GET(命中缓存或未命中)",方便对照
convert的输出排查问题。
五、Bug 报告:先判断归属,再隔离问题
CONTRIBUTING.md 把 Bug 定义为"由仓库代码引起的可演示问题",并给出三条撰写指南:
- 判断归属(Does it belong here?):先确认问题是 bootstrap-sass 的,还是上游 twbs/bootstrap 的。本仓库只分发"直接移植"的产物,上游未改动的文件不会在这里修改——因此样式/JS 本身的问题应反馈给上游。
- 搜索已有报告:用 issue 搜索确认问题是否已被报告,避免重复。
- 隔离问题:理想情况下提供精简的测试用例(reduced test case)与可运行示例,帮助维护者快速复现。
一份合格报告的必备信息包括:运行环境、复现步骤、出问题的浏览器与操作系统、期望结果,以及(可选)你定位到的嫌疑代码行与解决方案。文中给出的示例模板如下:
简短且有描述性的报告标题
问题摘要及出现该问题的浏览器/OS 环境。如合适,附上复现步骤。
- 第一步
- 第二步
- 后续步骤
<url>(精简测试用例链接)其他你认为与问题相关的信息,包括你怀疑导致问题的代码行及潜在解决方案。
六、Pull Request:修补转换器,而非 SCSS 产物
"We will not accept pull requests that modify the SCSS beyond fixing bugs caused byourcode!"这是仓库最鲜明的一条约束,含义为:除修复由 bootstrap-sass 自身代码引起的 Bug 外,不接受任何直接修改 SCSS 的 PR。由于 SCSS 由 converter script 从上游 LESS 自动转换而来,与样式/JS 本身相关但无关转换过程的问题应提交给上游 twbs/bootstrap。
具体到落地规则:
- 修复由本项目代码引起的 Bug 时,不要直接改 SCSS,而应修补转换器(即 tasks/converter/less_conversion.rb 及其子模块),再重新运行
rake convert让资产随之更新。 - 好的 PR 应聚焦在单一范围内,避免夹带无关提交;涉及大量工作或对项目某部分有实质性改动时,先开 issue 讨论再动手。
- 遵循项目编码约定(缩进、注释等),并同步更新与改动相关的文档。
这套"改转换器而不是改产物"的约定,配合上文的convert任务,构成了仓库的可持续维护闭环。
七、提交前的验证:测试与编译检查
仓库为"转换器改动"提供了多层自动验证,建议在提交前跑通:
- Rakefile 定义了
Rake::TestTask,默认rake会执行 test 下全部*_test.rb用例; - test/compilation_test.rb 用 SassC 分别编译
bootstrap与bootstrap/theme,只要不抛异常即通过,用于验证转换产物语法合法; - test/sass_test.rb 走 test/dummy_sass_only 目录(其 Gemfile 依赖
sassc与本地 path 的bootstrap-sass),通过 compile.rb 编译 import_all.scss 并断言输出中包含字体url(...eot...),验证字体路径注入正确; - test/node_sass_compile_test.sh 用 node-sass 二进制分别编译
_bootstrap.scss与bootstrap/_theme.scss,覆盖非 Ruby 生态的编译路径。
此外还有针对 Rails 集成(test/dummy_rails)与 Node.js Mincer(test/dummy_node_mincer)的测试,test/support/dummy_rails_integration.rb通过 Capybara + Poltergeist 启动真实 Rails 应用做端到端校验。改动转换器后运行这些用例,可以确认三类资产(SCSS/JS/fonts)均能正确产出并编译。
八、社区行为边界:Do not…
CONTRIBUTING.md 同时划清了 issue 跟踪器的使用边界:
- 不要将 issue 跟踪器用于个人支持请求(请使用 Stack Overflow 等社区渠道);
- 不要偏离主题或恶意刷屏,保持讨论聚焦并尊重他人意见。
该文档的协作规范参考了 html5-boilerplate 的 CONTRIBUTING 文本(文末已注明出处)。维护者欢迎聚焦、规范、经过验证的补丁——对 bootstrap-sass 而言,最受青睐的贡献形式,始终是"修复转换器,而不是修补转换产物"。
- 前端
- UI组件
【免费下载链接】bootstrap-sass
Official Sass port of Bootstrap 2 and 3.
相关推荐
NetBox 贡献指南:从 Bug 报告到 Pull Request 的完整协作流程
NetBox 贡献指南:从 Bug 报告到 Pull Request 的完整协作流程 NetBox 是一个开源的网络基础设施管理(IPAM/DCIM)平台,其代
后端网络数据建模Glances 贡献指南:从 Bug 报告到 Pull Request 的完整协作流程
Glances 贡献指南:从 Bug 报告到 Pull Request 的完整协作流程 本篇技术指南以 Glances 官方贡献文档( CONTRIBUTING
指标监控监控大盘CLI告警MCP 服务VitePress Markdown 扩展完全指南:内置语法增强与代码块高阶玩法
VitePress Markdown 扩展完全指南:内置语法增强与代码块高阶玩法 VitePress 内置了一整套开箱即用的 Markdown 扩展,涵盖标题锚
前端文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考