├── .codeclimate.yml ├── .editorconfig ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── codeowners ├── pull_request_template.md └── security ├── .gitignore ├── .pryrc ├── .rubocop.yml ├── .travis.yml ├── CHANGELOG.md ├── COPYING ├── Gemfile ├── README.md ├── Rakefile ├── jekyll-assets.gemspec ├── lib ├── jekyll-assets.rb └── jekyll │ ├── assets.rb │ └── assets │ ├── cache.rb │ ├── compressors │ ├── sassc.rb │ ├── scss.rb │ └── uglify.rb │ ├── config.rb │ ├── context.rb │ ├── default.rb │ ├── drop.rb │ ├── env.rb │ ├── errors.rb │ ├── errors │ └── unknown_hook.rb │ ├── extensible.rb │ ├── filters.rb │ ├── hook.rb │ ├── hook │ └── point.rb │ ├── html.rb │ ├── logger.rb │ ├── manifest.rb │ ├── patches │ ├── asset.rb │ ├── cached_environment.rb │ ├── functions.rb │ ├── obsolete.rb │ ├── site.rb │ └── writer.rb │ ├── plugins.rb │ ├── plugins │ ├── alternates.rb │ ├── bootstrap.rb │ ├── font-awesome.rb │ ├── frontmatter.rb │ ├── html.rb │ ├── html │ │ ├── audio.rb │ │ ├── component.rb │ │ ├── css.rb │ │ ├── defaults.rb │ │ ├── defaults │ │ │ ├── audio.rb │ │ │ ├── component.rb │ │ │ ├── css.rb │ │ │ ├── favicon.rb │ │ │ ├── img.rb │ │ │ ├── js.rb │ │ │ └── vid.rb │ │ ├── favicon.rb │ │ ├── img.rb │ │ ├── js.rb │ │ ├── pic.rb │ │ ├── svg.rb │ │ └── vid.rb │ ├── liquid.rb │ ├── magick.rb │ ├── optim.rb │ ├── prefixer.rb │ ├── proxy │ │ ├── magick.rb │ │ ├── optim.rb │ │ └── vips.rb │ ├── searcher.rb │ ├── srcmap.rb │ ├── srcmap │ │ ├── css.rb │ │ ├── javascript.rb │ │ └── writer.rb │ └── vips.rb │ ├── proxy.rb │ ├── reader.rb │ ├── tag.rb │ ├── url.rb │ ├── utils.rb │ └── version.rb ├── script ├── install ├── lint ├── report ├── script.d │ └── install ├── sync └── test └── spec ├── fixture ├── _assets │ ├── audio │ │ ├── audio.m4a │ │ └── audio.mp3 │ ├── components │ │ └── test.html │ ├── css │ │ ├── _partials │ │ │ └── partial.scss │ │ ├── bundle.scss │ │ ├── plugins │ │ │ ├── alternates.scss │ │ │ ├── botstrap.scss │ │ │ ├── closure_comments.css │ │ │ ├── compression.scss │ │ │ ├── fon-awesome.scss │ │ │ ├── frontmatter.scss │ │ │ └── liquid │ │ │ │ ├── basic1.liquid.scss │ │ │ │ ├── basic2.scss.liquid │ │ │ │ ├── complex.scss.liquid │ │ │ │ └── import.scss.liquid │ │ └── require.scss │ ├── img │ │ ├── gt_5k.jpg │ │ ├── img.bmp │ │ ├── img.gif │ │ ├── img.ico │ │ ├── img.jpg │ │ ├── img.png │ │ ├── img.svg │ │ ├── img.tiff │ │ ├── img.webp │ │ ├── lt_5k.jpg │ │ ├── lt_5k@1.5x.jpg │ │ ├── lt_5k@2x.jpg │ │ ├── plugins │ │ │ └── liquid │ │ │ │ ├── basic1.liquid.svg │ │ │ │ └── basic2.svg.liquid │ │ └── subdir │ │ │ ├── img.bmp │ │ │ ├── img.gif │ │ │ ├── img.jpg │ │ │ ├── img.png │ │ │ ├── img.svg │ │ │ ├── img.tiff │ │ │ └── img.webp │ ├── js │ │ ├── bundle.js │ │ ├── plugins │ │ │ └── compression.js │ │ └── require.js │ └── video │ │ ├── video.mp4 │ │ └── video.webm ├── _config.yml ├── _layouts │ └── default.html ├── _plugins │ └── hook.rb ├── component.html ├── defaults.html ├── index.html ├── loop.html ├── plugins │ ├── audio.html │ ├── html │ │ ├── defaults │ │ │ └── inline.html │ │ ├── favicon.html │ │ ├── img_inline.html │ │ ├── img_integrity.html │ │ ├── img_integrity_skip.html │ │ └── img_path.html │ ├── magick │ │ ├── double.html │ │ ├── half.html │ │ └── run.html │ ├── optim.html │ ├── searcher.html │ ├── searcher_lc.html │ ├── video.html │ └── vips │ │ ├── compress.html │ │ ├── double.html │ │ ├── format.html │ │ ├── half.html │ │ └── resize.html ├── tag │ ├── asset.html │ ├── attr.html │ ├── css.html │ ├── external.html │ ├── img.html │ ├── js.html │ ├── liquid.html │ ├── path.html │ └── pic.html ├── thief.html └── utils │ └── parse_liquid │ ├── assign.html │ └── ctx.html ├── rspec └── helper.rb ├── support ├── cache.rb ├── coverage.rb ├── execjs.rb ├── helpers.rb ├── profile.rb ├── shared.rb ├── silence.rb └── thief.rb └── tests └── lib └── jekyll └── assets ├── cache_spec.rb ├── config_spec.rb ├── context_spec.rb ├── default_spec.rb ├── drop_spec.rb ├── env_spec.rb ├── extensible_spec.rb ├── hook_spec.rb ├── html_spec.rb ├── logger_spec.rb ├── manifest_spec.rb ├── plugins ├── alternates_spec.rb ├── bootstrap_spec.rb ├── font-awesome_spec.rb ├── frontmatter_spec.rb ├── liquid_spec.rb ├── magick_spec.rb ├── optim_spec.rb ├── searcher_spec.rb ├── srcmap │ ├── css_spec.rb │ ├── javascript_spec.rb │ └── writer_spec.rb ├── srcmap_spec.rb └── vips_spec.rb ├── plugins_spec.rb ├── proxy_spec.rb ├── tag_spec.rb └── utils_spec.rb /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | plugins: 3 | rubocop: 4 | enabled: false 5 | ratings: 6 | paths: 7 | - "spec/tests/**.rb" 8 | - "lib/**.rb" 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | end_of_line = lf 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: envygeeks 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report an Issue! 4 | --- 5 | 6 | 12 | 13 | - [ ] I tried updating to the latest version 14 | - [ ] I can't, there is an issue 15 | - [ ] This is about an < latest 16 | - [ ] I understand older versions may be unsupported 17 | - [ ] I Am on Windows 18 | - [ ] Ubuntu Bash on Windows 19 | - [ ] Fedora Bash on Windows 20 | - [ ] Other Bash on Windows 21 | - [ ] I Am on Linux 22 | - [ ] Ubuntu 23 | - [ ] Fedora 24 | - [ ] CentOS 25 | - [ ] Redhat 26 | - [ ] Debian 27 | - [ ] I am on macOS 10.13 28 | - [ ] I am on macOS 10.14 29 | - [ ] I'm on Docker 30 | - [ ] I understand Docker may be unsupported 31 | 32 | ## Description 33 | 34 | 40 | 41 | ## Steps 42 | 43 | - Step 1 44 | - Step 2 45 | - Step 3 46 | 47 | ## Output 48 | 49 | ```sh 50 | # Doing stuff. 51 | # Doing more stuff. 52 | # Oh no error. 53 | ``` 54 | 55 | ## Expected 56 | 57 | 62 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an Idea! 4 | --- 5 | 6 | - [ ] This feature is not on the latest version 7 | 8 | ## Request 9 | 10 | 15 | 16 | ## Examples 17 | 18 | ```sh 19 | # Your example 20 | # Maybe multiple 21 | # Examples? 22 | ``` 23 | -------------------------------------------------------------------------------- /.github/codeowners: -------------------------------------------------------------------------------- 1 | * @envygeeks 2 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | - [ ] I have added or updated the specs/tests. 2 | - [ ] I have verified that the specs/tests pass on my computer. 3 | - [ ] I have not attempted to bump, or alter versions. 4 | - [ ] This is a documentation change. 5 | - [ ] This is a source change. 6 | 7 | ## Description 8 | 9 | 15 | -------------------------------------------------------------------------------- /.github/security: -------------------------------------------------------------------------------- 1 | * @envygeeks 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # -- 2 | # OS Level 3 | # -- 4 | .DS_Store 5 | 6 | # -- 7 | # Ruby 8 | # -- 9 | vendor/ 10 | coverage/ 11 | Gemfile.lock 12 | spec/fixture/site/ 13 | spec/fixture/result/ 14 | spec/fixture/out/ 15 | .bundle/ 16 | *.gem 17 | 18 | # -- 19 | # CodeClimate 20 | # -- 21 | cctr 22 | 23 | # -- 24 | # Jekyll 25 | # -- 26 | _site/ 27 | .jekyll-cache/ 28 | .jekyll-metadata 29 | .asset-cache/ 30 | site/ 31 | 32 | # -- 33 | # Rails 34 | # -- 35 | /db/*.sqlite3 36 | /npm-error.log 37 | .byebug_history 38 | /db/*.sqlite3-journal 39 | /config/application.yml 40 | /config/master.key 41 | /yarn-error.log 42 | /node_modules 43 | .pry_history 44 | /log 45 | /tmp 46 | 47 | # -- 48 | # Yarn 49 | # -- 50 | yarn.lock 51 | 52 | # -- 53 | # Editors 54 | # -- 55 | /.idea 56 | -------------------------------------------------------------------------------- /.pryrc: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Encoding: utf-8 4 | 5 | require "bundler/setup" 6 | require "jekyll/assets" 7 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_gem: 2 | envygeeks-rubocop: 3 | - rules.yml 4 | Layout/EmptyLineAfterGuardClause: 5 | Enabled: false 6 | Layout/ArgumentAlignment: 7 | EnforcedStyle: with_fixed_indentation 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | after_success: script/report 3 | before_install: 4 | - "gem install bundler" 5 | - "script/install" 6 | before_script: script/report before 7 | script: script/test 8 | sudo: false 9 | cache: 10 | bundler: true 11 | directories: 12 | - vendor/bundle 13 | - node_modules 14 | env: 15 | global: 16 | secure: "\ 17 | h+3g4a4eXVBiZWcnSJ39lTlhv+JmRrPJPOW7Qvs0u3ix4nZLd4DhDnsmOmu2gRze9BFhX3Ga1\ 18 | 6clq2Kku75Ty9pgZ9/8jrN+CcPbqv3rQHdHIaaQf5eFirr5Lw0eY02etRf9G6pHEdIyMSOrXU\ 19 | GTwDtjR+BT65M5qESGniBXTd8=\ 20 | " 21 | matrix: 22 | - JEKYLL_BRANCH="master" 23 | - JEKYLL_VERSION="~> 3.8.0" 24 | - JEKYLL_VERSION="~> 4.0.0" 25 | - LINTING=true 26 | rvm: 27 | - 2.6 28 | - 2.7 29 | matrix: 30 | fast_finish: true 31 | allow_failures: 32 | - env: JEKYLL_BRANCH="master" 33 | notifications: 34 | email: 35 | recipients: 36 | - jordon@envygeeks.io 37 | on_success: change 38 | on_failure: change 39 | branches: 40 | only: 41 | - master 42 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | v4.0.0 2 | 3 | - Changed the way raw_precompile works. Before it would only work if the 4 | path was included inside of the sources, now it will take a path (that can be 5 | anywhere) and a hash argument `strip` that is a Regexp that can be used 6 | to clean the path pre-write... all assets still end up inside of the 7 | `destination` path. 8 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright 2012 - 2015 Aleksey V Zapparov 2 | Copyright 2015 - 2018 Jordon Bedwell 3 | 4 | Permission to use, copy, modify, and/or distribute this software for 5 | any purpose with or without fee is hereby granted, provided that the 6 | above copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 13 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 14 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - MIT License 3 | # rubocop:disable Bundler/DuplicatedGem 4 | # Encoding: utf-8 5 | 6 | source "https://rubygems.org" 7 | gemspec 8 | 9 | s_version = "~> 4.0" 10 | j_version = "~> 4.0" 11 | gem "sprockets", ENV["SPROCKETS_VERSION"] || s_version, require: false 12 | if ENV["JEKYLL_VERSION"] 13 | gem "jekyll", ENV["JEKYLL_VERSION"], { 14 | require: false, 15 | } 16 | elsif ENV["JEKYLL_BRANCH"] 17 | gem "jekyll", { 18 | git: "https://github.com/jekyll/jekyll", 19 | branch: ENV["JEKYLL_BRANCH"], 20 | } 21 | else 22 | gem "jekyll", j_version 23 | end 24 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2017 - 2018 - MIT License 3 | # Source: https://github.com/envygeeks/devfiles 4 | # Author: Jordon Bedwell 5 | # Encoding: utf-8 6 | 7 | task default: [:spec] 8 | task(:spec) { exec "script/test" } 9 | task(:test) { exec "script/test" } 10 | Dir.glob("script/rake.d/*.rake").each do |v| 11 | load v 12 | end 13 | -------------------------------------------------------------------------------- /jekyll-assets.gemspec: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # rubocop:disable Metrics/BlockLength 4 | # Encoding: utf-8 5 | 6 | $LOAD_PATH.unshift(File.expand_path("lib", __dir__)) 7 | require "jekyll/assets/version" 8 | 9 | Gem::Specification.new do |s| 10 | s.require_paths = ["lib"] 11 | s.version = Jekyll::Assets::VERSION 12 | s.homepage = "http://github.com/jekyll/jekyll-assets/" 13 | s.authors = ["Jordon Bedwell", "Aleksey V Zapparov", "Zachary Bush"] 14 | s.email = %w(jordon@envygeeks.io ixti@member.fsf.org zach@zmbush.com) 15 | s.files = %w(Rakefile Gemfile README.md LICENSE) + Dir["lib/**/*"] 16 | s.summary = "Assets for Jekyll" 17 | s.name = "jekyll-assets" 18 | s.license = "MIT" 19 | 20 | s.description = <<~TXT 21 | A drop-in Jekyll Plugin that provides an asset pipeline for JavaScript, 22 | CSS, SASS, SCSS. Based around Sprockets (from Rails) and just as powereful 23 | it provides everything you need to manage assets in Jekyll. 24 | TXT 25 | 26 | s.required_ruby_version = ">= 2.6.0" 27 | s.add_runtime_dependency("execjs", "~> 2.7") 28 | s.add_runtime_dependency("nokogiri", "~> 1.10") 29 | s.add_runtime_dependency("activesupport", ">= 5", "< 7") 30 | s.add_runtime_dependency("sprockets", "~> 4.0.beta7") 31 | s.add_runtime_dependency("fastimage", ">= 1.8", "~> 2.0") 32 | s.add_runtime_dependency("liquid-tag-parser", ">= 1", "< 3") 33 | s.add_runtime_dependency("sassc", ">= 1.11", "< 3.0") 34 | s.add_runtime_dependency("jekyll", ">= 3.5", "< 5.0") 35 | s.add_runtime_dependency("jekyll-sanity", "~> 1.2") 36 | s.add_runtime_dependency("pathutil", "~> 0.16") 37 | s.add_runtime_dependency("extras", "~> 0.2") 38 | 39 | s.add_development_dependency("rspec", "~> 3.4") 40 | s.add_development_dependency("uglifier", "~> 4.1") 41 | s.add_development_dependency("mini_racer", "~> 0.1") 42 | s.add_development_dependency("image_optim", "~> 0.25") 43 | s.add_development_dependency("image_optim_pack", "~> 0.5") 44 | s.add_development_dependency("font-awesome-sass", "~> 5.0") 45 | s.add_development_dependency("luna-rspec-formatters", "~> 3.2") 46 | s.add_development_dependency("envygeeks-rubocop", "= 1.0.0") 47 | s.add_development_dependency("autoprefixer-rails", "~> 9.7") 48 | s.add_development_dependency("babel-transpiler", "~> 0.7") 49 | s.add_development_dependency("mini_magick", "~> 4.2") 50 | s.add_development_dependency("simplecov", "~> 0.16") 51 | s.add_development_dependency("bootstrap", "~> 4.0") 52 | s.add_development_dependency("ruby-vips", "~> 2") 53 | s.add_development_dependency("crass", "~> 1.0") 54 | s.add_development_dependency("rake", "~> 13") 55 | s.add_development_dependency("pry", "~> 0") 56 | end 57 | -------------------------------------------------------------------------------- /lib/jekyll-assets.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Encoding: utf-8 4 | 5 | require_relative "jekyll/assets" 6 | -------------------------------------------------------------------------------- /lib/jekyll/assets.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Author: Jordon Bedwell 4 | # Encoding: utf-8 5 | 6 | require "pathutil" 7 | require "jekyll/assets/version" 8 | require "active_support/hash_with_indifferent_access" 9 | require "active_support/core_ext/hash/indifferent_access" 10 | require "active_support/core_ext/hash/deep_merge" 11 | require "forwardable/extended" 12 | require "jekyll/sanity" 13 | require "sprockets" 14 | require "jekyll" 15 | 16 | module Jekyll 17 | module Assets 18 | autoload :Cache, "jekyll/assets/cache" 19 | autoload :Config, "jekyll/assets/config" 20 | autoload :Default, "jekyll/assets/default" 21 | autoload :Drop, "jekyll/assets/drop" 22 | autoload :Env, "jekyll/assets/env" 23 | autoload :Errors, "jekyll/assets/errors" 24 | autoload :Extensible, "jekyll/assets/extensible" 25 | autoload :Filters, "jekyll/assets/filters" 26 | autoload :Hook, "jekyll/assets/hook" 27 | autoload :HTML, "jekyll/assets/html" 28 | autoload :Logger, "jekyll/assets/logger" 29 | autoload :Manifest, "jekyll/assets/manifest" 30 | autoload :Proxy, "jekyll/assets/proxy" 31 | autoload :Tag, "jekyll/assets/tag" 32 | autoload :Url, "jekyll/assets/url" 33 | autoload :Utils, "jekyll/assets/utils" 34 | 35 | # -- 36 | # Setup Jekyll Assets 37 | # @see require_patches! 38 | # @see before_hook! 39 | # @see after_hook! 40 | # @return [nil] 41 | # -- 42 | def self.setup! 43 | require_patches! 44 | %i(read write).each do |v| 45 | send(:"#{v}_hook!") 46 | end 47 | end 48 | 49 | # -- 50 | # Require all our patches 51 | # @return [nil] 52 | # -- 53 | def self.require_patches! 54 | dir = Pathutil.new(__dir__).join("assets", "patches") 55 | dir.children do |v| 56 | unless v.directory? 57 | require v 58 | end 59 | end 60 | end 61 | 62 | # -- 63 | # Initialize the environment 64 | # @note this happens after Jekyll read 65 | # @return [nil] 66 | # -- 67 | def self.read_hook! 68 | Jekyll::Hooks.register :site, :post_read, priority: 99 do |o| 69 | unless o.sprockets 70 | Env.new(o) 71 | end 72 | end 73 | end 74 | 75 | # -- 76 | # Write all the assets 77 | # @note this happens after Jekyll write 78 | # @return [nil] 79 | # -- 80 | def self.write_hook! 81 | Jekyll::Hooks.register :site, :post_write, priority: 99 do |o| 82 | o&.sprockets&.write_all 83 | end 84 | end 85 | 86 | # -- 87 | private_class_method :write_hook! 88 | private_class_method :require_patches! 89 | private_class_method :read_hook! 90 | 91 | # -- 92 | setup! 93 | Filters.register 94 | Drop.register 95 | Tag.register 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /lib/jekyll/assets/cache.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Author: Jordon Bedwell 4 | # Encoding: utf-8 5 | 6 | module Jekyll 7 | module Assets 8 | class Cache 9 | extend Forwardable 10 | def_delegator :instance, :get 11 | def_delegator :instance, :fetch 12 | def_delegator :instance, :clear 13 | def_delegator :instance, :set 14 | Upstream = Sprockets::Cache 15 | 16 | # 17 | # @inherit StandardError 18 | # Error for when the cache dir is not absolute. 19 | # @return [nil] 20 | # 21 | class RelativeCacheDir < StandardError 22 | def initialize 23 | super 'Cache dir must be absolute' 24 | end 25 | end 26 | 27 | # 28 | # Initialize a new instance 29 | # @return [self] 30 | # 31 | def initialize(dir:, manifest:, config:) 32 | @manifest = manifest 33 | @dir = validate_and_make_cache(dir) 34 | @config = config 35 | end 36 | 37 | # 38 | # Whether or not caching is enabled 39 | # @note configure with caching.enabled 40 | # @return [true, false] 41 | # 42 | def enabled? 43 | @config[:caching][ 44 | :enabled 45 | ] 46 | end 47 | 48 | # 49 | # The type of caching. 50 | # @note configure with caching.type 51 | # @return [String] 52 | # 53 | def type 54 | @config[:caching][ 55 | :type 56 | ] 57 | end 58 | 59 | # 60 | # Return the class for the type. 61 | # @note configure with caching.type 62 | # @return [ 63 | # , 64 | # , 65 | # , 66 | # ] 67 | # 68 | def upstream 69 | return Upstream::NullStore unless enabled? 70 | return Upstream::MemoryStore.new(4096) if type == 'memory' 71 | Upstream::FileStore.new(@dir) 72 | end 73 | 74 | # 75 | # Create the cache. 76 | # @note configure with cache 77 | # @return [Upstream] 78 | # 79 | def instance 80 | return @instance if defined?(@instance) 81 | @instance = begin 82 | out = Upstream.new(upstream, Logger) 83 | @manifest.new_manifest? \ 84 | ? out.tap(&:clear) 85 | : out 86 | end 87 | end 88 | 89 | # 90 | # Make the dir, and validate it 91 | # @raise bad dir if it's not absolute 92 | # @return [Pathutil] 93 | # 94 | def validate_and_make_cache(dir) 95 | dir = Pathutil.new(dir) 96 | raise RelativeCacheDir unless dir.absolute? 97 | dir.tap(&:mkdir_p) 98 | end 99 | end 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /lib/jekyll/assets/compressors/sassc.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2017 - 2018 - MIT License 3 | # Author: Jordon Bedwell 4 | # Encoding: utf-8 5 | 6 | module Jekyll 7 | module Assets 8 | module Compressors 9 | class SassC < Sprockets::SasscCompressor 10 | def call(input) 11 | out = super(input) 12 | Hook.trigger :asset, :after_compression do |h| 13 | !out.is_a?(Hash) \ 14 | ? out = h.call(input, out, 'text/css') 15 | : out[:data] = h.call( 16 | input, out[:data], 17 | 'text/css' 18 | ) 19 | end 20 | 21 | out 22 | end 23 | end 24 | 25 | # -- 26 | Sprockets.register_compressor 'text/css', :assets_sassc, SassC 27 | Hook.register :env, :after_init, priority: 3 do |e| 28 | e.css_compressor = nil 29 | next unless e.asset_config[:compression] 30 | Utils.activate('sassc') do 31 | e.css_compressor = :assets_sassc 32 | end 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/jekyll/assets/compressors/scss.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2017 - 2018 - MIT License 3 | # Author: Jordon Bedwell 4 | # Encoding: utf-8 5 | 6 | module Jekyll 7 | module Assets 8 | module Compressors 9 | class Scss < Sprockets::SassCompressor 10 | def call(input) 11 | out = super(input) 12 | Hook.trigger :asset, :after_compression do |h| 13 | !out.is_a?(Hash) \ 14 | ? out = h.call(input, out, 'text/css') 15 | : out[:data] = h.call( 16 | input, out[:data], 17 | 'text/css' 18 | ) 19 | end 20 | 21 | out 22 | end 23 | end 24 | 25 | # -- 26 | Sprockets.register_compressor 'text/css', :assets_scss, Scss 27 | Hook.register :env, :after_init, priority: 3 do |e| 28 | next if Utils.activate('sassc') 29 | 30 | e.css_compressor = nil 31 | next unless e.asset_config[:compression] 32 | e.css_compressor = :assets_scss 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/jekyll/assets/compressors/uglify.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2017 - 2018 - MIT License 3 | # Author: Jordon Bedwell 4 | # Encoding: utf-8 5 | 6 | module Jekyll 7 | module Assets 8 | module Compressors 9 | class Uglify < Sprockets::UglifierCompressor 10 | def call(input) 11 | out = super(input) 12 | Hook.trigger :asset, :after_compression do |h| 13 | !out.is_a?(Hash) \ 14 | ? out = h.call(input, out, 'application/javascript') 15 | : out[:data] = h.call( 16 | input, out[:data], 17 | 'application/javascript' 18 | ) 19 | end 20 | 21 | out 22 | end 23 | end 24 | 25 | Sprockets.register_compressor "application/javascript", :assets_uglify, Uglify 26 | Hook.register :env, :after_init, priority: 3 do |e| 27 | enable = e.asset_config[:compression] 28 | config = e.asset_config[:compressors][:uglifier].symbolize_keys 29 | e.js_compressor = nil 30 | 31 | if enable && Utils.javascript? && Utils.activate("uglifier") 32 | e.js_compressor = Uglify.new(config) 33 | end 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/jekyll/assets/config.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Author: Jordon Bedwell 4 | # Encoding: utf-8 5 | 6 | module Jekyll 7 | module Assets 8 | class Config < HashWithIndifferentAccess 9 | Hook.add_point :env, :before_merge 10 | DIRECTORIES = %i( 11 | css fonts images 12 | videos audios components 13 | javascript video audio 14 | image img js 15 | ).freeze 16 | 17 | # 18 | # The source directories 19 | # @note _assets, assets, and base 20 | # @return [Array] 21 | # 22 | def self.sources 23 | return @sources if defined?(@sources) 24 | 25 | sources_a = [] 26 | sources_b = [] 27 | sources_c = [] 28 | 29 | DIRECTORIES.map do |name| 30 | sources_a.push(format('assets/%s', name: name)) 31 | sources_b.push(name.to_s) 32 | sources_c.push( 33 | format( 34 | '_assets/%s', { 35 | name: name 36 | } 37 | ) 38 | ) 39 | end 40 | 41 | @sources = \ 42 | sources_a | 43 | sources_b | 44 | sources_c 45 | end 46 | 47 | def self.development 48 | return @development if defined?(@development) 49 | @development = { 50 | digest: true, 51 | precompile: [], 52 | source_maps: true, 53 | destination: '/assets', 54 | digest_algorithm: :sha512, 55 | compression: false, 56 | raw_precompile: [], 57 | sources: sources, 58 | full_url: false, 59 | defaults: {}, 60 | gzip: false, 61 | 62 | compressors: { 63 | uglifier: { 64 | comments: false, 65 | harmony: true, 66 | }, 67 | }, 68 | 69 | caching: { 70 | path: '.jekyll-cache/assets', 71 | enabled: true, 72 | type: 'file', 73 | }, 74 | 75 | cdn: { 76 | baseurl: false, 77 | destination: false, 78 | url: nil, 79 | } 80 | } 81 | end 82 | 83 | def self.production 84 | return @production if defined?(@production) 85 | @production = development.merge( 86 | source_maps: false, 87 | compression: true 88 | ) 89 | end 90 | 91 | def self.defaults 92 | return development if Jekyll.dev? 93 | production 94 | end 95 | 96 | def initialize(config) 97 | super(self.class.defaults) 98 | Hook.trigger(:config, :before_merge) do |h| 99 | h.call( 100 | self 101 | ) 102 | end 103 | 104 | deep_merge!(config) 105 | self[:sources] = \ 106 | Array(self[:sources]) | 107 | self.class.defaults[ 108 | :sources 109 | ] 110 | end 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /lib/jekyll/assets/context.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Encoding: utf-8 4 | 5 | module Jekyll 6 | module Assets 7 | module Context 8 | # -- 9 | # Allows you to get an asset by it's path. 10 | # @note this SASS helper fully supports proxy arguments. 11 | # @param _ [Hash] this is unused but necessary. 12 | # @param path [String] the path. 13 | # @return [String] the path. 14 | # -- 15 | def asset_path(path, _ = {}) 16 | ctx1 = Liquid::ParseContext.new 17 | ctx2 = Liquid::Context.new({}, {}, site: environment.jekyll) 18 | Jekyll::Assets::Tag.new("img", "#{path} @path", ctx1) 19 | .render(ctx2) 20 | end 21 | end 22 | end 23 | end 24 | 25 | # -- 26 | Jekyll::Assets::Hook.register :env, :after_init do 27 | context_class.send(:include, 28 | Jekyll::Assets::Context 29 | ) 30 | end 31 | -------------------------------------------------------------------------------- /lib/jekyll/assets/default.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Encoding: utf-8 4 | 5 | module Jekyll 6 | module Assets 7 | class Default < Extensible 8 | # -- 9 | # @param [String] type the content type. 10 | # @param [Hash] args the args from the liquid tag. 11 | # Get all of the static defaults. 12 | # @return [Hash] 13 | # -- 14 | def self.get(type:, args:) 15 | rtn = Default.inherited.select do |o| 16 | o.for?( 17 | type: type, 18 | args: args, 19 | ) 20 | end 21 | 22 | ida = HashWithIndifferentAccess.new 23 | rtn.sort { |v| v.internal? ? 1 : - 1 }.each_with_object(ida) do |v, h| 24 | h.deep_merge!(v.static) 25 | end 26 | end 27 | 28 | # -- 29 | # Set non-static defaults around the asset. 30 | # @param [Hash] args the arguments to work on. 31 | # @param [String] type the content type to work with. 32 | # @param [Sprockets::Asset] asset the asset. 33 | # @param [Env] env the environment. 34 | # @return nil 35 | # -- 36 | def self.set(args, asset:, ctx:) 37 | set_static(args, asset: asset) 38 | rtn = Default.inherited.select do |o| 39 | o.for?(type: asset.content_type, args: args) 40 | end 41 | 42 | rtn.each do |o| 43 | o.new( 44 | args: args, 45 | asset: asset, 46 | ctx: ctx, 47 | ).run 48 | end 49 | end 50 | 51 | # -- 52 | def self.set_static(args, asset:) 53 | get(type: asset.content_type, args: args).each do |k, v| 54 | k = k.to_sym 55 | 56 | unless args.key?(k) 57 | args[k] = args[k].is_a?(Hash) ? 58 | args[k].deep_merge(v) : v 59 | end 60 | end 61 | end 62 | 63 | # -- 64 | # @param [Hash] hash the defaults. 65 | # @note this is used from your inherited class. 66 | # Allows you to set static defaults for your defaults. 67 | # @return nil 68 | # -- 69 | def self.static(hash = nil) 70 | return @static ||= {}.with_indifferent_access if hash.nil? 71 | static.deep_merge!(hash) 72 | end 73 | 74 | # -- 75 | # Search for set_* methods and run those setters. 76 | # @note this shouldn't be used directly by end-users. 77 | # @return nile 78 | # -- 79 | def run 80 | methods = self.class.instance_methods - Object.instance_methods 81 | methods.grep(%r!^set_!).each do |v| 82 | send(v) 83 | end 84 | end 85 | 86 | # -- 87 | def config 88 | @config ||= env.asset_config[:defaults][ 89 | self.class.name.split("::").last.downcase 90 | ] 91 | end 92 | end 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /lib/jekyll/assets/drop.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Encoding: utf-8 4 | 5 | require "liquid/drop" 6 | require "fastimage" 7 | 8 | module Jekyll 9 | module Assets 10 | class Drop < Liquid::Drop 11 | extend Forwardable::Extended 12 | def initialize(path, jekyll:) 13 | @path = path.to_s 14 | @sprockets = jekyll.sprockets 15 | @jekyll = jekyll 16 | @asset = nil 17 | end 18 | 19 | rb_delegate :width, to: :dimensions, type: :hash 20 | rb_delegate :height, to: :dimensions, type: :hash 21 | rb_delegate :basename, to: :File, args: :@path 22 | rb_delegate :content_type, to: :asset 23 | rb_delegate :integrity, to: :asset 24 | rb_delegate :filename, to: :asset 25 | 26 | # -- 27 | # @todo this needs to move to `_url` 28 | # @return [String] the prefixed and digested path. 29 | # The digest path. 30 | # -- 31 | def digest_path 32 | @sprockets.prefix_url(asset.digest_path) 33 | end 34 | 35 | # -- 36 | # Image dimensions if the asest is an image. 37 | # @return [Hash] the dimensions. 38 | # @note this can break easily. 39 | # -- 40 | def dimensions 41 | @dimensions ||= begin 42 | img = FastImage.size(asset.filename.to_s) 43 | 44 | { 45 | "width" => img[0], 46 | "height" => img[1], 47 | } 48 | rescue => e 49 | Logger.error e 50 | end 51 | end 52 | 53 | private 54 | def asset 55 | @asset ||= begin 56 | @sprockets.find_asset!(@path) 57 | end 58 | end 59 | 60 | # -- 61 | # Register the drop creator. 62 | # @return [nil] 63 | # -- 64 | public 65 | def self.register 66 | Jekyll::Hooks.register :site, :pre_render do |s, h| 67 | if s.sprockets 68 | h["assets"] = s.sprockets.to_liquid_payload 69 | end 70 | end 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/jekyll/assets/env.rb: -------------------------------------------------------------------------------- 1 | # Frozen-string-literal: true 2 | # Copyright: 2012 - 2020 - ISC License 3 | # Encoding: utf-8 4 | 5 | require_relative 'reader' 6 | 7 | dir = Pathutil.new(__dir__) 8 | dir.join('compressors').children.map( 9 | &method( 10 | :require 11 | ) 12 | ) 13 | 14 | module Jekyll 15 | module Assets 16 | class Env < Sprockets::Environment 17 | extend Forwardable::Extended 18 | include Utils 19 | 20 | # -- 21 | attr_reader :manifest 22 | attr_accessor :assets_to_write 23 | attr_reader :asset_config 24 | attr_reader :jekyll 25 | 26 | # -- 27 | def initialize(jekyll) 28 | @asset_config = Config.new(jekyll.config['assets'] ||= {}) 29 | Hook.trigger :env, :before_init do |h| 30 | instance_eval(&h) 31 | end 32 | 33 | super() 34 | @jekyll = jekyll 35 | @assets_to_write = [] 36 | @manifest = Manifest.new(self, in_dest_dir) 37 | @jekyll.sprockets = self 38 | @total_time = 0.000000 39 | @logger = Logger 40 | @cache = nil 41 | 42 | setup_sources! 43 | setup_digesting! 44 | ignore_caches! 45 | precompile! 46 | 47 | Hook.trigger :env, :after_init do |h| 48 | instance_eval(&h) 49 | end 50 | end 51 | 52 | # -- 53 | def skip_gzip? 54 | !asset_config[:gzip] 55 | end 56 | 57 | # -- 58 | def find_asset(asset, *args) 59 | msg = "Searched for, and rendered #{asset} in %