Are you happy with your logging solution? Would you help us out by taking a 30-second survey? Click here

jekyll-assets

:art: Asset pipelines for Jekyll.

Subscribe to updates I use jekyll-assets


Statistics on jekyll-assets

Number of watchers on Github 877
Number of open issues 9
Average time to close an issue 5 days
Main language Ruby
Average time to merge a PR 3 days
Open pull requests 12+
Closed pull requests 21+
Last commit over 1 year ago
Repo Created about 7 years ago
Repo Last Updated over 1 year ago
Size 3.48 MB
Homepage https://envygeeks...
Organization / Authorenvygeeks
Contributors25
Page Updated
Do you use jekyll-assets? Leave a review!
View open issues (9)
View jekyll-assets activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating jekyll-assets for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

Code Climate Code Climate Travis CI Donate Gem Version Gem DL

Looking for information on what's changed? See https://envygeeks.io/2017/11/21/jekyll-assets-3-released

Jekyll Assets

Jekyll Assets is a drop in asset pipeline that uses Sprockets to build specifically for Jekyll. It utilizes Sprockets, and Jekyll to try and achieve a clean, and extensible assets platform that supports plugins, caching, converting your assets. It even supports proxying of said assets in a way that does not interfere with either Sprockets, or Jekyll, or your own source. By default you can add Jekyll Assets to your Gemfile, as a plugin, and have it act as a drop-in replacement for Jekyll's basic SASS processors, with you only having to add it to your Gemfile, and updating your <img>, and <link>.

Installing

gem "jekyll-assets", group: :jekyll_plugins
gem "jekyll-assets", git: "https://github.com/envygeeks/jekyll-assets", group: :jekyll_plugins
gem "jekyll-assets", "~> x.x.alpha", group: :jekyll_plugins

System Requirements

  • ruby: 2.3+
  • sprockets: 3.3+
  • jekyll: 3.5+

If you'd like SourceMaps, or faster Sprockets, opt to use Sprockets 4.0, you can use it by placing it to your Gemfile.

gem "sprockets", "~> 4.0.beta", {
  require: false
}

Configuration

The configuration file is the same as Jekyll's, which is _config.yml. Except we use the special key called assets inside of that file. All values listed below are default, you need not copy these into your configuration file unless you plan to change a value. Setting a value makes it explicit, and shared across both **production, and **development.

source_maps: true # false on JEKYLL_ENV=production
destination: "/assets"
compression: true
gzip: false
defaults:
   js: { integrity: false } # true on JEKYLL_ENV=production
  css: { integrity: false } # true on JEKYLL_ENV=production
  img: { integrity: false } # true on JEKYLL_ENV=production
caching:
  path: ".jekyll-cache/assets"
  type: file # Possible values: memory, file
  enabled: true
# --
# Assets you wish to always have compiled.
#   This can also be combined with raw_precompile which
#   copies assets without running through the pipeline
#   making them ultra fast.
# --
precompile: []
raw_precompile: [
  #
]
# --
# baseurl: whether or not to append site.baseurl
# destination: the folder you store them in on the CDN.
# url: the CDN url (fqdn, or w/ identifier).
# --
cdn:
  baseurl: false
  destination: false
  url: null
# --
# These are all default. No need to add them
#   Only use this if you have more.
# --
sources:
  - assets/css
  - assets/fonts
  - assets/images
  - assets/videos
  - assets/javascript
  - assets/video
  - assets/image
  - assets/img
  - assets/js
  - _assets/css
  - _assets/fonts
  - _assets/images
  - _assets/videos
  - _assets/javascript
  - _assets/video
  - _assets/image
  - _assets/img
  - _assets/js
  - css
  - fonts
  - images
  - videos
  - javascript
  - video
  - image
  - img
  - js
plugins:
  css: { autoprefixer: {}}
  img: { optim: {}}

Tag {% asset %}, <img>

{% asset src @magick:2x alt='This is my alt' %}
{% asset src @magick:2x alt='This is my alt' %}
<img src="src" asset="@magick:2x" alt="This is my alt">
<img src="src" alt="This is my alt" asset>

Defaults

We provide several defaults that get set when you run an asset, depending on content type, this could be anything from type, all the way to integrity. If there is a default attribute you do not wish to be included, you can disable the attribute with !attribute, and it will be skipped over.

{% asset img.png !integrity %}
{% asset bundle.css !type   %}

Arguments

Our tags will take any number of arguments, and convert them to HTML, and even attach them to your output if the HTML processor you use accepts that kind of data. This applies to anything but hashes, and arrays. So adding say, a class, or id, is as easy as doing id="val" inside of your tag arguments.

Built In

Arg Description Type Return Type
@path Path */* text
@data data URI */* text
@inline CSS <style> text/css text/html
text/svg+xml XML image/svg+xml text/svg+xml
JavaScript <script> application/javascript text/html
Image <img> image/* text/html
srcset Responsive <img> image/* text/html
srcset + @pic Responsive <pic> image/* text/html

Jekyll Assets uses @envygeeks liquid-tag-parser which supports advanced arguments (hash based arguments) as well as array based arguments. When you see something like k1:sk1=val it will get converted to k1 = { sk1: "val" } in Ruby. To find out more about how we process tags you should visit the documentation for liquid-tag-parser

Responsive Images

Jekyll Assets has the concept of responsive images, using the picture (when using @pic w/ srcset) and the <img> tag when using srcset. If you ship multiple srcset with your image, we will proxy, build and then ship out a picture/img tag with any number of source/srcset, and in the case of picture, with the original image being the image.

<picture> usage, requires @pic
Example
{% asset img.png @pic
    srcset:max-width="800 2x"
    srcset:max-width="600 1.5x"
    srcset:max-width="400 1x"
      %}
<picture>
  <source srcset="1.png 2x"   media="(max-width:800px)">
  <source srcset="2.png 1.5x" media="(max-width:600px)">
  <source srcset="3.png 1x"   media="(max-width:400px)">
  <img src="img.png">
</picture>
<img> usage
Example
{% asset img.png
    srcset:width="400 2x"
    srcset:width="600 1.5x"
    srcset:width="800 1x"
      %}

{% asset img.png
    srcset:width=400
    srcset:width=600
    srcset:width=800
      %}
<img srcset="1.png   2x, 2.png 1.5x, 3.png   1x">
<img srcset="1.png 400w, 2.png 600w, 3.pnx 800w">
Args
Arg Type Description @pic Only
width Width [Density] Resize, set srcset="<Src> <<Width>px/Density>"
min-width Width [Density] Resize, set media="(min-width: <Width>px)"
max-width Width [Density] Resize, set media="(max-width: <Width>px)"
sizes Any Your value, unaltered, unparsed.
media Any Your value, unaltered, unparsed.

If you set media, w/ max-width, min-width, we will not ship media, we will simply resize and assume you know what you're doing. Our parser is not complex, and does not make a whole lot of assumptions on your behalf, it's simple and only meant to make your life easier. In the future we may make it more advanced.

Liquid

We support liquid arguments for tag values (but not tag keys), and we also support Liquid pre-processing (with your Jekyll context) of most files if they end with .liquid. This will also give you access to our filters as well as their filters, and Jekyll's filters, and any tags that are globally available.

{% asset '{{ site.bg_img }}' %}
{% asset '{{ site.bg_img }}' proxy:key='{{ value }}' %}
{% asset {{\ site.bg_img\ }} %}

.sass, .scss

body {
  background-image: asset_url("'{{ site.bg_img }}'");
  background-image: asset_url("'{{ site.bg_img }}' proxy:key='{{ value }}'");
  background-image: asset_url("{{\ site.bg_img\ }}");
}

.liquid.ext

.ext.liquid

.bg {
  background: url(asset_path("{{ site.background_image }}"));
}

You have full access to your entire global context from any liquid processing we do. Depending on where you do it, you might or might not also have access to your local (page) context as well. You can also do whatever you like, and be as dynamic as you like, including full loops, and conditional Liquid, since we pre-process your text files. On Sprockets 4.x you can use .liquid.ext and .ext.liquid, but because of the way Sprockets 3.x works, we have opted to only allow the default extension of .ext.liquid when running on Old Sprockets (AKA 3.x.) If you would like Syntax + Liquid you should opt to install Sprockets 4.x so you can get the more advanced features.

Importing

In order to import your Liquid pre-processed assets inside of Liquid or JS you should use a Sprockets //require=, Sprockets does not integrate that deeply into JavaScript and SASS to allow you to @import and pre-process.

.sass, .scss Helpers

We provide two base helpers, asset_path to return the path of an asset, and asset_url which will wrap asset_path into a url() for you, making it easy for you to extract your assets and their paths inside of SCSS. All other helpers that Sprockets themselves provide will use our asset_path helper, so you can use them like normal, including with Liquid

body {
  background-image: asset_url("img.png");
}

Proxies, and Other Arguments

Any argument that is supported by our regular tags, is also supported by our .sass/.scss helpers, with a few obvious exceptions (like srcset). This means that you can wrap your assets into magick if you wish, or imageoptim or any other proxy that is able to spit out a path for you to use. The general rule is, that if it returns a path, or @data then it's safe to use within .scss/.sass, otherwise it will probably throw.

body {
  background-image: asset_url("img.png @magick:half")
}

Note: we do not validate your arguments, so if you send a conflicting argument that results in invalid CSS, you are responsible for that, in that if you ship us srcset we might or might not throw, depending on how the threads are ran. So it might ship HTML if you do it wrong, and it will break your CSS, this is by design so that if possible, in the future, we can allow more flexibility, or so that plugins can change based on arguments.

List

We provide all your assets as a hash of Liquid Drops so you can get basic info that we wish you to have access to without having to prepare the class. Note: The keys in the assets array are the names of the original files, e.g., use *.scss instead of *.css.

{{ assets["bundle.css"].content_type }} => "text/css"
{{ assets["images.jpg"].width  }} => 62
{{ assets["images.jpg"].height }} => 62

The current list of available accessors:

Method Description
content_type The RFC content type
height The asset height (if available)
filename The full path to the assets actual file
width The asset width (if available)
digest_path The prefixed path
integrity The SRI hash (currently sha256)

Looping

{% for k,v in assets %}
  {{ k }}
{% endfor %}

Dynamic

Using Liquid Drop assets, you can check whether an asset is present.

{% if assets[page.image] %}{% img '{{ page.image }}' %}
{% else %}
  {% img default.jpg %}
{% endif %}

Filter

{{ src | asset:"@magick:2x magick:quality:92" }}

Polymer WebComponents

We have basic support for WebComponents when using Sprockets ~> 4.0.0.beta, this will allow you to place your HTML in the _assets/components folder, {% asset myComponent.html %}, and get an import, you can place your regular JS files inside of the normal structure.

Example

test.html

<!DOCTYPE html>
<html>
  <head>
    {% asset webcomponents.js %}
    {% asset test.html %}
  </head>
  <body>
    <contact-card starred>
      {% asset profile.jpg %}
      <span>Your Name</span>
    </contact-card>
  </body>
</body>

_assets/components/test.html

<dom-module id="contact-card">
  <template>
    <style>/* ... */</style>
    <slot></slot>
    <iron-icon icon="star" hidden$="{{!starred}}"></iron-icon>
  </template>
  <script>
    class ContactCard extends Polymer.Element {
      static get is() { return "contact-card"; }
      static get properties() {
        return {
          starred: { type: Boolean, value: false }
        }
      }
    }
    customElements.define(ContactCard.is, ContactCard);
  </script>
</dom-module>

Hooks

Point Name Instance Args
:env :before_init
:env :after_init
:env :after_write
:config :before_merge Config{}
:asset :before_compile Asset, Manifest
:asset :after_compression input{}, output{}, type=/

Example

Jekyll::Assets::Hook.register :env, :before_init do
  append_path "myPluginsCustomPath"
end
Jekyll::Assets::Hook.register :config, :init do |c|
  c.deep_merge!({
    plugins: {
      my_plugin: {
        opt: true
      }
    }
  })
end

Plugin Hooks

Your plugin can also register it's own hooks on our Hook system, so that you can trigger hooks around your stuff as well, this is useful for extensive plugins that want more power.

Jekyll::Assets::Hook.add_point(:plugin, :hook)
Jekyll::Assets::Hook.trigger(:plugin, :hook)  { |v| v.call(:arg) }
Jekyll::Assets::Hook.trigger(:plugin, :hook) do |v|
  instance_eval(&v)
end

Default Plugins

Google Closure Alternates

gem "crass"

Once crass is added, we will detect vendor prefixes, and add /* @alternate */ to them, with or without compression enabled, and with protections against compression stripping.

Font Awesome

gem "font-awesome-sass"
@import "font-awesome-sprockets";
@import "font-awesome";
html {
  // ...
}

CSS Auto-Prefixing

gem "autoprefixer-rails"
assets:
  autoprefixer:
    browsers:
    - "last 2 versions"
    - "IE > 9"

Bootstrap

gem "boostrap-sass" # 3.x
gem "bootstrap"     # 4.x
@import 'bootstrap'
html {
  // ...
}
//=require _bootstrap.css
//=require bootstrap/_reboot.css

ImageMagick

gem "mini_magick"

Args

See the MiniMagick docs to get an idea what <value> can be.

Name Accepts Value
magick:compress
magick:resize
magick:format*
magick:quality
magick:rotate
magick:gravity
magick:crop
magick:flip
@magick:double
@magick:half

* magick:format requires an ext or a valid MIME content type like image/jpeg or .jpg. We will ImageMagick -format on your behalf with that information by getting the extension.

ImageOptim

gem "image_optim"

Check the ImageOptim to get idea about configuration options.

assets:
  plugins:
    img:
      optim:
        default:
          verbose: true
        zero_png:
          advpng:
            level: 0
          optipng:
            level: 0
          pngout:
            strategy: 4

Args

Name Accepts Value
@image_optim:preset*

*Where preset is the name of the preset.

Building Your Own Plugins

Globals

Name Class
@env Jekyll::Assets::Env
@args Liquid::Tag::Parser{}
@jekyll Jekyll::Site
@asset Sprockets::Asset

HTML

Name Class Type
@doc Nokogiri:: XML::Document image/svg+xml
@doc Nokogiri::HTML::Document image/*

Migrating from Earlier Versions

Configuration

Before

cdn: https://example.com

After

cdn:
  url: https://example.com

Images/CSS/JS

Before

{% css css.css %}
{% img image.jpg width:60 class:image %}
{% js js.js %}

After

{% asset css.css %}
{% asset image.jpg width=60 class=image %}
{% asset js.js %}

Custom Tags

Before

<link rel="apple-touch-icon-precomposed" href="{% asset_path icon.png %}">
<link rel="apple-touch-icon-precomposed" href="{% asset_data icon.png %}">

After

<link rel="apple-touch-icon-precomposed" href="{% asset icon.png @path %}">
<link rel="apple-touch-icon-precomposed" href="{% asset icon.png @data %}">
jekyll-assets open issues Ask a question     (View All Issues)
  • almost 3 years Improving asset pipeline speed
  • about 3 years Inconsistent environment logic
  • about 3 years Conflict with `where` filter and document titles which contain spaces
  • about 3 years Errno::EMFILE: Too many open files @ rb_sysopen
  • about 3 years JekyllAssets and Jekyll 3.3
  • about 3 years Making LESS work
  • about 3 years Jekyll's cache not updating CSS
  • about 3 years JS & CSS compression not working
  • about 3 years Understanding JekyllAssets
  • about 3 years LiquidException: Unknown proxy argument
  • about 3 years Changing the `digest_path`
  • about 3 years SHA384 integrity support broken when assets are compressed
  • about 3 years CSS compression not working with LESS
  • about 3 years asset_path, asset_url font_path is not honoring the site.baseurl in sass files
  • about 3 years Error: undefined method `logical_path' for nil:NilClass
  • over 3 years Append assets to `site.static_files`
  • over 3 years Cannot pass classes to inlined SVGs
  • over 3 years Inconsistent building of image assets in SCSS (asset_path)
  • over 3 years Getting started
  • over 3 years building js file from _data file fails
  • over 3 years how to call image_optim for all image assets after all transforms
  • over 3 years Improve error messages
  • over 3 years Double :img in Jekyll::Assets::Liquid::Filters::ACCEPTABLE_FILTERS
  • over 3 years Anyway to include jekyll asset_path logic into markdown?
  • over 3 years Add default headers to Jekyll Serve for integrity.
  • over 3 years Support preprocess removal of "---"
  • over 3 years Support jekyll-sass-converter options.
  • over 3 years Move documentation to the Wiki
  • over 3 years image_optim in Jekyll 3 Assets
  • almost 4 years image with relative path
jekyll-assets open pull requests (View All Pulls)
  • docs(uglify): it's uglifier
  • Rails assets
  • RSpec: addons/proxies -> proxies
  • Enable mutating content type from proxies
  • Fix samples for JavaScript
  • Fix missing `image` filter
  • Allow cache dirs outside the main source dir
  • Support magick for asset_path
  • Proxy: digest based on the file too, fix #472
  • Activating Open Collective
  • Migration examples.
  • Update tag.rb
jekyll-assets questions on Stackoverflow (View All Questions)
  • jekyll-multiple-languages-plugin not excluding "assets" directory created by jekyll-assets
  • Setting background image with Jekyll-Assets
  • Bootstrap file not found when using built-in vendors with jekyll-assets
  • Image Not Copied by Jekyll-Assets
  • Can I use the octopress image tag with jekyll-assets asset_path?
  • Why images folder is not copied when generating an Octopress with jekyll-assets blog?
jekyll-assets list of languages used
Other projects in Ruby