Skip to content

Commit

Permalink
Create 2024-02-13-jekyll-gem-resolver.md
Browse files Browse the repository at this point in the history
  • Loading branch information
cr7pt0gr4ph7 authored Feb 21, 2024
1 parent fd50bfe commit 2fef26f
Showing 1 changed file with 172 additions and 0 deletions.
172 changes: 172 additions & 0 deletions _posts/2024-02-13-jekyll-gem-resolver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
type: article
title: Using SASS files from Ruby gems with Jekyll
tags: ["Jekyll"]
article_header:
type: overlay
theme: dark
background_color: "#363649"
background_image:
src: assets/img/posts/2024-02/pexels-jessica-lewis-thepaintedsquare-583847.jpg
alignment: 61%
---

This blog, as well as my other static websites, are all built using [Jekyll][jekyll].
It's a great tool, and really easy to work with, because it takes care of related build steps
like compiling your SCSS sources to CSS.
While doing some refactoring, I wanted to switch from using a pre-built version of the
[Bootstrap CSS framework][bootstrap] to building it from its SCSS source.

This involves three things (as outlined in the [Bootstrap documentation][bootstrap-build-docs]):

1. Getting the Bootstrap SCSS files
2. Turning the SCSS files into pure CSS
3. Transforming the resulting CSS files using Autoprefixer to add vendor prefixes

### How to: Build Bootstrap from source using Jekyll

As described by [this blog post][blog-bootstrap-jekyll], that is quite easy:

1. Copy all SCSS files from Bootstrap into your source repository.
2. Use the [jekyll-sass-converter] plugin. As its already bundled with Jekyll by default, we don't have to do anything special.
3. Use the [jekyll-autoprefixer] plugin.

Well... that's good, except for the part number 1 _"Copy all SCSS files from Bootstrap"_.
Isn't that what we have package managers for?
There already is an official [bootstrap rubygem][bootstrap-gem], so preferably I would like to use that.
Just add it to your `Gemfile`, and reference it in your `_config.yml`:

```ruby
# Gemfile
gem "bootstrap", "~> 5.3.2"
```

```yaml
# _config.yml
sass:
load_paths:
- ???
```
...but how to actually reference the `bootstrap` gem in your `_config.yml`?

Turns out that Jekyll does not have a built-in facility for referencing files from Gems directly,
so I just wrote a [small Jekyll plugin][jekyll-gem-resolver] that allows me to do just that:

```yaml
# _config.yml
sass:
load_paths:
- 'gem:bootstrap/assets/stylesheets'
gem_resolver:
transform: # Specify where gem references might be found
- sass.load_paths
```

Instead of just transforming every string starting with `gem:` in the configuration (which could have unintended side-effects)
or hard-coding the paths where to look for gem references (which would not work well with additional plugins),
I made the parts of the configuration where gem references are replaced [fully configurable](https://github.com/cr7pt0gr4ph7/jekyll-gem-resolver?tab=readme-ov-file#path-syntax).

#### Caveat: Pinning execjs to `2.7.0`

Although not related to my plugin but to `jekyll-autoprefixer`, I hope that this PSA saves some people the headache I had:

Due to [a bug with ExecJS][execjs-bug] (which is used by jekyll-autoprefixer/[`autoprefixer-rails`][autoprefixer-rails] internally to actually run
[autoprefixer]),
one has to explicitly force the ExecJS gem to a last version not affected by the bug, which is version 2.7.0
to avoid some confusing runtime errors:

```ruby
# Gemfile
# Required to avoid runtime errors in jekyll-autoprefixer caused by ExecJS 2.8.0 and later
gem "execjs", "= 2.7.0"
```


### The full picture

My whole setup (excluding totally unrelated parts) for building Bootstrap from the [bootstrap rubygem][bootstrap-gem],
including Autoprefixer, now looks like this:

```yaml
# _config.yml
plugins:
- jekyll-gem-resolver
- jekyll-autoprefixer
sass:
load_paths:
- 'gem:bootstrap/assets/stylesheets'
gem_resolver:
transform:
- sass.load_paths
```

Besides the `bootstrap` gem, you also have to reference the `jekyll-gem-resolver` and `jekyll-autoprefixer` gems in your `Gemfile`:

```ruby
# Gemfile
source "https://rubygems.org"
gem "jekyll", "~> 4.3.3"
# Acquire bootstrap to use its SASS sources
gem "bootstrap", "~> 5.3.2"
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-gem-resolver", "~> 0.0.3"
gem "jekyll-autoprefixer", "~> 1.0"
end
# Required to avoid runtime errors in jekyll-autoprefixer caused by ExecJS 2.8.0 and later
gem "execjs", "= 2.7.0"
# The remainder of this file is just taken from the default Jekyll template:
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
platforms :mingw, :x64_mingw, :mswin, :jruby do
gem "tzinfo", ">= 1", "< 3"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
# do not have a Java counterpart.
gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
```

Importing files from the Bootstrap gem looks just like any other SCSS code:

```scss
// assets/css/default.scss

// ...
@import "bootstrap";
// ...
```

Neat!

### Conclusion

I've published the plugin on GitHub and RubyGems.
You can find the documentation and source code for the plugin [**here**][jekyll-gem-resolver].

[jekyll]: https://jekyllrb.com/
[bootstrap]: https://github.com/twbs/bootstrap
[bootstrap-build-docs]: https://getbootstrap.com/docs/5.3/getting-started/download/#source-files
[bootstrap-gem]: https://github.com/twbs/bootstrap-rubygem
[blog-bootstrap-jekyll]: https://medium.com/codex/how-to-add-bootstrap-5-sass-to-jekyll-e3b189f71552

[jekyll-sass-converter]: https://github.com/jekyll/jekyll-sass-converter
[jekyll-autoprefixer]: https://github.com/vwochnik/jekyll-autoprefixer
[jekyll-autoprefixer-sourcemaps]: https://github.com/vwochnik/jekyll-autoprefixer/pull/16
[jekyll-gem-resolver]: https://github.com/cr7pt0gr4ph7/jekyll-gem-resolver
[jekyll-gem-resolver-gem]: https://rubygems.org/gems/jekyll-gem-resolver
[autoprefixer]: https://github.com/postcss/autoprefixer
[autoprefixer-rails]: https://github.com/ai/autoprefixer-rails
[execjs-bug]: https://github.com/rails/execjs/issues/99

0 comments on commit 2fef26f

Please sign in to comment.