distorted-jekyll 0.5.2 → 0.5.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +661 -0
- data/README.md +6 -10
- data/lib/distorted-jekyll.rb +79 -0
- data/lib/distorted-jekyll/13th-style.rb +58 -0
- data/lib/distorted-jekyll/_config_default.yml +79 -0
- data/lib/distorted-jekyll/blocks.rb +16 -0
- data/lib/distorted-jekyll/error_code.rb +24 -0
- data/lib/distorted-jekyll/floor.rb +148 -0
- data/lib/distorted-jekyll/injection_of_love.rb +305 -0
- data/lib/distorted-jekyll/invoker.rb +400 -0
- data/lib/distorted-jekyll/molecule/abstract.rb +238 -0
- data/lib/distorted-jekyll/molecule/font.rb +29 -0
- data/lib/distorted-jekyll/molecule/image.rb +105 -0
- data/lib/distorted-jekyll/molecule/last-resort.rb +54 -0
- data/lib/distorted-jekyll/molecule/pdf.rb +88 -0
- data/lib/distorted-jekyll/molecule/svg.rb +59 -0
- data/lib/distorted-jekyll/molecule/text.rb +74 -0
- data/lib/distorted-jekyll/molecule/video.rb +43 -0
- data/lib/distorted-jekyll/monkey_business/jekyll/cleaner.rb +54 -0
- data/lib/distorted-jekyll/static/font.rb +42 -0
- data/lib/distorted-jekyll/static/image.rb +55 -0
- data/lib/distorted-jekyll/static/lastresort.rb +28 -0
- data/lib/distorted-jekyll/static/pdf.rb +53 -0
- data/lib/distorted-jekyll/static/state.rb +141 -0
- data/lib/distorted-jekyll/static/svg.rb +52 -0
- data/lib/distorted-jekyll/static/text.rb +57 -0
- data/lib/distorted-jekyll/static/video.rb +90 -0
- data/lib/distorted-jekyll/template/13th-style.css +78 -0
- data/lib/distorted-jekyll/template/error_code.liquid +3 -0
- data/lib/distorted-jekyll/template/font.liquid +32 -0
- data/lib/distorted-jekyll/template/image.liquid +32 -0
- data/lib/distorted-jekyll/template/lastresort.liquid +20 -0
- data/lib/distorted-jekyll/template/pdf.liquid +14 -0
- data/lib/distorted-jekyll/template/svg.liquid +32 -0
- data/lib/distorted-jekyll/template/text.liquid +32 -0
- data/lib/distorted-jekyll/template/video.liquid +11 -0
- metadata +41 -6
data/README.md
CHANGED
@@ -1,19 +1,16 @@
|
|
1
|
-
#
|
1
|
+
# Jekyll::DistorteD
|
2
2
|
|
3
|
-
`DistorteD` is a multimedia framework for Jekyll websites.
|
4
|
-
|
5
|
-
Right now this repo contains two Gems:
|
6
|
-
- [`DistorteD-Jekyll`](https://rubygems.org/gems/distorted-jekyll) contains anything and everything that depends on Jekyll.
|
7
|
-
- [`DistorteD-Ruby`](https://rubygems.org/gems/distorted) contains just the abstract media file format handling code. It's separate so I can use those functions in other contexts and/or easily replace the Ruby core if necessary.
|
3
|
+
`DistorteD-Jekyll` is a multimedia framework for Jekyll websites.
|
8
4
|
|
9
5
|
## Motivation
|
10
6
|
|
11
|
-
|
7
|
+
DistorteD is my solution for displaying photos, videos, and other types of media on [cooltrainer.org](https://cooltrainer.org) due to my dissatisfaction with every other solution I could find.
|
12
8
|
|
13
9
|
My previous approach was similar to what's [described here](https://eduardoboucas.com/blog/2014/12/07/including-and-managing-images-in-jekyll.html), with small/medium/large image size variations generated with [Jekyll-MiniMagick](https://github.com/MattKevan/Jekyll-MiniMagick-new).
|
14
10
|
|
15
11
|
Here are some already-existing ways to put pictures on your Jekyll site that are worth your consideration before choosing DistorteD:
|
16
12
|
|
13
|
+
- Octopress' [image_tag](https://github.com/imathis/octopress/blob/master/plugins/image_tag.rb) plugin.
|
17
14
|
- [jekyll-responsive-image](https://github.com/wildlyinaccurate/jekyll-responsive-image)
|
18
15
|
- [jekyll_picture_tag](https://rbuchberger.github.io/jekyll_picture_tag/)
|
19
16
|
- [jekyll-gallery-generator](https://github.com/ggreer/jekyll-gallery-generator)
|
@@ -95,7 +92,7 @@ will be transformed into.
|
|
95
92
|
%}
|
96
93
|
```
|
97
94
|
|
98
|
-
|
95
|
+
or, for a DD grid:
|
99
96
|
|
100
97
|
```
|
101
98
|
{% distort %}
|
@@ -157,11 +154,10 @@ Clone the DistorteD repository and modify your Jekyll `Gemfile` to refer to your
|
|
157
154
|
|
158
155
|
```
|
159
156
|
gem 'distorted-jekyll', :path => '~/repos/DistorteD/DistorteD-Jekyll/'[, :branch => 'NEW-SENSATION']
|
160
|
-
gem 'distorted', :path => '~/repos/DistorteD/DistorteD-Ruby/'[, :branch => 'NEW-SENSATION']
|
161
157
|
```
|
162
158
|
|
163
159
|
The `DistorteD-Jekyll` Gem will automatically use its local sibling `DistorteD-Ruby` Gem if used in this way.
|
164
160
|
|
165
161
|
## License
|
166
162
|
|
167
|
-
|
163
|
+
The gem is available as open source under the terms of the [GNU Affero General Public License version 3](https://opensource.org/licenses/AGPL-3.0).
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'distorted-jekyll/13th-style'
|
2
|
+
require 'distorted-jekyll/blocks'
|
3
|
+
require 'distorted-jekyll/injection_of_love'
|
4
|
+
require 'distorted-jekyll/invoker'
|
5
|
+
|
6
|
+
|
7
|
+
FATAL_FURY = true
|
8
|
+
UPDATE_RUBY = "Please use DistorteD with Ruby 2.7.0 or later"
|
9
|
+
def update_ruby
|
10
|
+
if defined? RUBY_PLATFORM
|
11
|
+
if (/freebsd/ =~ RUBY_PLATFORM) != nil
|
12
|
+
return 'pkg install lang/ruby27'
|
13
|
+
elsif (/darwin/ =~ RUBY_PLATFORM) != nil
|
14
|
+
return 'brew upgrade ruby'
|
15
|
+
elsif (/win/ =~ RUBY_PLATFORM) != nil
|
16
|
+
return 'https://rubyinstaller.org/'
|
17
|
+
elsif (/linux/ =~ RUBY_PLATFORM) != nil
|
18
|
+
if File.exists?('/etc/lsb-release')
|
19
|
+
lsb = File.read('/etc/lsb-release')
|
20
|
+
if (/Ubuntu|LinuxMint/ =~ lsb) != nil
|
21
|
+
return 'https://www.brightbox.com/docs/ruby/ubuntu/#installation'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
return 'https://github.com/rbenv/ruby-build'
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# I want to be able to use:
|
31
|
+
# - Array#dig and Hash#dig (Ruby 2.3): https://bugs.ruby-lang.org/issues/11643
|
32
|
+
# - Lonely operator (Ruby 2.3): https://bugs.ruby-lang.org/issues/11537
|
33
|
+
# - Hash#transform_keys (Ruby 2.5): https://bugs.ruby-lang.org/issues/13583
|
34
|
+
# - Enumerable#filter_map (Ruby 2.7): https://bugs.ruby-lang.org/issues/5663
|
35
|
+
# https://blog.saeloun.com/2019/05/25/ruby-2-7-enumerable-filter-map.html
|
36
|
+
# - 'Real' kwargs in preparation for Ruby 3: https://bugs.ruby-lang.org/issues/14183
|
37
|
+
# https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
|
38
|
+
if [
|
39
|
+
Hash.method_defined?(:dig), # 2.3
|
40
|
+
Hash.method_defined?(:transform_keys), # 2.5
|
41
|
+
Enumerable.method_defined?(:filter_map), # 2.7
|
42
|
+
].all?
|
43
|
+
# Monkey-patch preferred_extensions iff we're going to load.
|
44
|
+
# My JPEGs coming out with a '.jpeg' file extension just annoys me so much.
|
45
|
+
require 'distorted/monkey_business/mnemoniq'
|
46
|
+
|
47
|
+
# Monkey-patch Jekyll::Cleaner to not nuke DistorteD-generated variations
|
48
|
+
# for our media files. This makes DistorteD fast!
|
49
|
+
require 'distorted-jekyll/monkey_business/jekyll/cleaner'
|
50
|
+
|
51
|
+
# Register DistorteD's entrypoint class with Liquid.
|
52
|
+
# `Invoker` will mix in the proper handler module for the given media.
|
53
|
+
Liquid::Template.register_tag('distorted', Jekyll::DistorteD::Invoker)
|
54
|
+
|
55
|
+
# Register a block version for arranging multiple pieces of media.
|
56
|
+
Liquid::Template.register_tag('distort', Jekyll::DistorteD::BLOCKS)
|
57
|
+
|
58
|
+
# Register a tag for basic DistorteD CSS.
|
59
|
+
Liquid::Template.register_tag('13th_style', Jekyll::DistorteD::ThirteenthStyle)
|
60
|
+
|
61
|
+
# Transform Markdown image syntax ![alt](url.jpg "title")
|
62
|
+
# to instances of our liquid tag {% distorted %}
|
63
|
+
# Available hooks can be seen here:
|
64
|
+
# https://github.com/jekyll/jekyll/blob/master/lib/jekyll/hooks.rb
|
65
|
+
# `:documents` does not seem to include `_pages` but does include `_posts`.
|
66
|
+
Jekyll::Hooks.register(:pages, :pre_render, &md_injection)
|
67
|
+
Jekyll::Hooks.register(:posts, :pre_render, &md_injection)
|
68
|
+
|
69
|
+
else
|
70
|
+
# Example of how this looks with the outdated Ruby 2.5 on my Mint 19 laptop:
|
71
|
+
#
|
72
|
+
# Bundler::GemRequireError: There was an error while trying to load the gem 'distorted-jekyll'.
|
73
|
+
# Gem Load Error is: Please use DistorteD with Ruby 2.7.0 or later: https://www.brightbox.com/docs/ruby/ubuntu/#installation
|
74
|
+
if FATAL_FURY
|
75
|
+
raise RuntimeError.new("#{UPDATE_RUBY}: #{update_ruby}")
|
76
|
+
else
|
77
|
+
Jekyll.logger.info('DistorteD', "#{UPDATE_RUBY}: #{update_ruby}")
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
# Slip in and out of phenomenon
|
3
|
+
require 'liquid/tag'
|
4
|
+
require 'liquid/tag/parser'
|
5
|
+
|
6
|
+
# Explicitly required for l/t/parser since a1cfa27c27cf4d4c308da2f75fbae88e9d5ae893
|
7
|
+
require 'shellwords'
|
8
|
+
|
9
|
+
|
10
|
+
module Jekyll
|
11
|
+
module DistorteD
|
12
|
+
class ThirteenthStyle < Liquid::Tag
|
13
|
+
|
14
|
+
TAB_SEQUENCE = ' '.freeze # two spaces
|
15
|
+
|
16
|
+
def initialize(tag_name, arguments, liquid_options)
|
17
|
+
super
|
18
|
+
|
19
|
+
# Liquid leaves argument parsing totally up to us.
|
20
|
+
# Use the envygeeks/liquid-tag-parser library to wrangle them.
|
21
|
+
parsed_arguments = Liquid::Tag::Parser.new(arguments)
|
22
|
+
|
23
|
+
# Specify how many levels to indent printed output.
|
24
|
+
# Indentation will apply to all lines after the first,
|
25
|
+
# because the first line's output will fall at the same
|
26
|
+
# place as our Liquid tag invocation.
|
27
|
+
@tabs = parsed_arguments[:tabs] || 0
|
28
|
+
end
|
29
|
+
|
30
|
+
# This is going to go away in a future Liquid version
|
31
|
+
# and render_to_output_buffer will be the standard approach.
|
32
|
+
# I'm going ahead and using it since we are building strings here.
|
33
|
+
def render(context)
|
34
|
+
return render_to_output_buffer(context, '')
|
35
|
+
end
|
36
|
+
|
37
|
+
def render_to_output_buffer(context, output)
|
38
|
+
css_filename = File.join(File.dirname(__FILE__), 'template'.freeze, '13th-style.css'.freeze)
|
39
|
+
|
40
|
+
# Use IO.foreach() to call a block on each line of our template file
|
41
|
+
# without slurping the entire file into memory like File.read() / File.readlines()
|
42
|
+
File.foreach(css_filename).with_index do |line, line_num|
|
43
|
+
# Don't indent the first line of the CSS file, because the first line
|
44
|
+
# will print starting at the position of our {% 13thStyle %} Liquid tag.
|
45
|
+
unless line_num == 0
|
46
|
+
output << TAB_SEQUENCE * @tabs
|
47
|
+
end
|
48
|
+
output << line
|
49
|
+
end
|
50
|
+
# Remove CSS comments from output so I can leave notes there
|
51
|
+
# without bloating up my output.
|
52
|
+
# Based on C-shebang-style comment regex from MRE3
|
53
|
+
return output.gsub(/\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//, '')
|
54
|
+
end
|
55
|
+
|
56
|
+
end # ThirteenthStyle
|
57
|
+
end # DistorteD
|
58
|
+
end # Jekyll
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Override any or all of this default configuration in your Jekyll site's `_config.yml`!
|
2
|
+
|
3
|
+
# Is it possible to do a Set of Hashes using the Set syntax in YAML?
|
4
|
+
# It works with the Array syntax, so that's what I'm using here,
|
5
|
+
# but keep in mind any Arrays will be converted to Sets when loaded,
|
6
|
+
# so duplicate Array values will be compacted!
|
7
|
+
|
8
|
+
standard_image: &standard_image
|
9
|
+
- tag: full
|
10
|
+
crop: none
|
11
|
+
- tag: small
|
12
|
+
width: 400
|
13
|
+
height: 400
|
14
|
+
media: "(max-width: 400px)"
|
15
|
+
- tag: medium
|
16
|
+
width: 800
|
17
|
+
height: 800
|
18
|
+
media: "(min-width: 400px) and (max-width: 800px)"
|
19
|
+
- tag: large
|
20
|
+
width: 1500
|
21
|
+
height: 1500
|
22
|
+
media: "(min-width: 800px)"
|
23
|
+
|
24
|
+
standard_text: &standard_text
|
25
|
+
? image/png
|
26
|
+
? image/webp
|
27
|
+
|
28
|
+
distorted:
|
29
|
+
|
30
|
+
# Liquid template caching is default as of Jekyll 4.0,
|
31
|
+
# but it can be disabled if needed.
|
32
|
+
# I just can't think of when it would be needed :)
|
33
|
+
cache_templates: true
|
34
|
+
|
35
|
+
# Should unrecognized media-types fall back to a bare
|
36
|
+
# <img> tag around the original media file?
|
37
|
+
# If not, the site build will fail when an unrecognized
|
38
|
+
# file is encountered.
|
39
|
+
last_resort: true
|
40
|
+
|
41
|
+
# Configure DistorteD format changes by media_type, then by sub_type.
|
42
|
+
# The list of target formats is plain text, media_type/sub_type.
|
43
|
+
# These are mostly based on IANA's official Media Types list:
|
44
|
+
# https://www.iana.org/assignments/media-types/media-types.xhtml
|
45
|
+
# but with some custom additions like using 'gif-sequence' for
|
46
|
+
# animated GIF and leaving 'image/gif' to refer to single-frame GIFs.
|
47
|
+
changes:
|
48
|
+
image:
|
49
|
+
jpeg:
|
50
|
+
? image/jpeg
|
51
|
+
? image/webp
|
52
|
+
png:
|
53
|
+
? image/png
|
54
|
+
? image/webp
|
55
|
+
gif:
|
56
|
+
? image/gif
|
57
|
+
? image/png
|
58
|
+
? image/webp
|
59
|
+
gif-sequence:
|
60
|
+
? image/gif-sequence
|
61
|
+
svg:
|
62
|
+
? image/svg+xml
|
63
|
+
? image/png
|
64
|
+
? image/webp
|
65
|
+
text:
|
66
|
+
plain: *standard_text
|
67
|
+
x-nfo: *standard_text
|
68
|
+
font:
|
69
|
+
ttf:
|
70
|
+
? image/png
|
71
|
+
? image/webp
|
72
|
+
|
73
|
+
outer_limits:
|
74
|
+
image:
|
75
|
+
jpeg: *standard_image
|
76
|
+
png: *standard_image
|
77
|
+
webp: *standard_image
|
78
|
+
font:
|
79
|
+
ttf: *standard_image
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
module Jekyll
|
3
|
+
module DistorteD
|
4
|
+
class BLOCKS < Liquid::Block
|
5
|
+
|
6
|
+
def initialize(tag_name, arguments, liquid_options)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(context)
|
11
|
+
"<div class=\"distorted-block\">#{super}</div>"
|
12
|
+
end
|
13
|
+
|
14
|
+
end # BLOCKS
|
15
|
+
end # DistorteD
|
16
|
+
end # Jekyll
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'distorted/error_code'
|
2
|
+
|
3
|
+
|
4
|
+
module Jekyll
|
5
|
+
module DistorteD
|
6
|
+
class OutOfDateLibraryError < LoadError
|
7
|
+
end
|
8
|
+
|
9
|
+
# The built-in NotImplementedError is for "when a feature is not implemented
|
10
|
+
# on the current platform", so make our own more appropriate ones.
|
11
|
+
class MediaTypeNotImplementedError < StandardDistorteDError
|
12
|
+
attr_reader :media_type, :name
|
13
|
+
def initialize(name)
|
14
|
+
super("No supported media type for #{name}")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class MediaTypeNotFoundError < StandardDistorteDError
|
18
|
+
attr_reader :media_type, :name
|
19
|
+
def initialize(name)
|
20
|
+
super("Failed to detect media type for #{name}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'distorted/monkey_business/hash'
|
2
|
+
require 'yaml'
|
3
|
+
require 'jekyll'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
|
7
|
+
module Jekyll
|
8
|
+
module DistorteD
|
9
|
+
class Floor
|
10
|
+
|
11
|
+
# Top-level config key (once stringified) for Jekyll and Default YAML.
|
12
|
+
CONFIG_ROOT = :distorted
|
13
|
+
|
14
|
+
# Filename for default config YAML. Should be a sibling of this file.
|
15
|
+
# Don't move this file or the YAML defaults without changing this.
|
16
|
+
DEFAULT_CONFIG_FILE_NAME = '_config_default.yml'.freeze
|
17
|
+
DEFAULT_CONFIG_PATH = File.join(File.dirname(__FILE__), DEFAULT_CONFIG_FILE_NAME).freeze
|
18
|
+
|
19
|
+
# Separator character for pretty-printing config hierarchy.
|
20
|
+
PP_SEPARATOR = "\u21e2 ".encode('utf-8').freeze
|
21
|
+
|
22
|
+
# Path separator is almost always '/' internally, but support
|
23
|
+
# ALT_SEPARATOR platforms too.
|
24
|
+
# On Lunix - Ruby 2.7:
|
25
|
+
# irb(main):003:0> File::ALT_SEPARATOR
|
26
|
+
# => nil
|
27
|
+
# irb(main):004:0> File::SEPARATOR
|
28
|
+
# => "/"
|
29
|
+
PATH_SEPARATOR = (File::ALT_SEPARATOR || File::SEPARATOR).freeze
|
30
|
+
|
31
|
+
|
32
|
+
# Generic main config-loading function that will search, in order:
|
33
|
+
# - The memoized pre-transformed config data store in-memory.
|
34
|
+
# - Jekyll's Site config, for a passed-in site or for the default site.
|
35
|
+
# - DistorteD's Gem-internal default config YAML.
|
36
|
+
#
|
37
|
+
# Optionally provide a class to be used as a fallback for missing keys.
|
38
|
+
def self.config(*keys, **kw)
|
39
|
+
# Symbolize for our internal representation of the config path.
|
40
|
+
# The Jekyll config and default config are both YAML, so we want string
|
41
|
+
# keys for them. Go ahead and prepend the top-level search key here too.
|
42
|
+
memo_keys = keys.compact.map(&:to_sym).to_set
|
43
|
+
search_keys = keys.compact.map(&:to_s).map(&:freeze)
|
44
|
+
# Pretty print the config path for logging.
|
45
|
+
log_key = search_keys.join(PP_SEPARATOR.to_s).freeze
|
46
|
+
# Initialize memoization class variable as a Hash that will return nil
|
47
|
+
# for any key access that doesn't already contain something.
|
48
|
+
@@memories ||= Hash.new { |h,k| h[k] = h.class.new(&h.default_proc) }
|
49
|
+
# Try to load a memoized config if we can, to skip any filesystem
|
50
|
+
# access and data transformation steps.
|
51
|
+
config = @@memories&.dig(*memo_keys)
|
52
|
+
unless config.nil?
|
53
|
+
if config.is_a?(TrueClass) || config.is_a?(FalseClass)
|
54
|
+
return config
|
55
|
+
elsif config.is_a?(Enumerable)
|
56
|
+
unless config.empty?
|
57
|
+
# Can't check this at the top level because True/FalseClass
|
58
|
+
# don't respond to this message.
|
59
|
+
return config
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# The key isn't memoized. Look for it first in Jekyll's Site config.
|
65
|
+
# Is it even possible to have more than one Site? Support being passed
|
66
|
+
# a `site` object just in case, but taking the first one should be fine.
|
67
|
+
site = kw[:site] || Jekyll.sites.first
|
68
|
+
# Get the config, or nil if the queried config path doesn't exist.
|
69
|
+
loaded_config = site.config.dig(*search_keys)
|
70
|
+
Jekyll.logger.debug(['_config', log_key].join(PP_SEPARATOR.to_s).concat(':'.freeze), loaded_config || 'No data'.freeze)
|
71
|
+
if loaded_config.nil?
|
72
|
+
# The wanted config key didn't exist in the Site config, so let's
|
73
|
+
# try our defaults!
|
74
|
+
# This file will always be small enough for a one-shot read.
|
75
|
+
default_config = YAML.load(File.read(DEFAULT_CONFIG_PATH))
|
76
|
+
loaded_config = default_config.dig(*search_keys)
|
77
|
+
Jekyll.logger.debug(['Default', log_key].join(PP_SEPARATOR.to_s).concat(':'.freeze), loaded_config || 'No data'.freeze)
|
78
|
+
end
|
79
|
+
# Was the desired config key found in the Gem defaults?
|
80
|
+
if loaded_config.nil?
|
81
|
+
# Nope.
|
82
|
+
return nil
|
83
|
+
else
|
84
|
+
# Symbolize any output keys and values, and convert Arrays and Ruby::YAML
|
85
|
+
# Sets-as-Hashes to Ruby stdlib Sets.
|
86
|
+
# Returning a Set instead of an Array should be fine since none of our
|
87
|
+
# configs can (read: should) contain duplicate values for any reason.
|
88
|
+
loaded_config = symbolic(set_me_free(loaded_config))
|
89
|
+
end
|
90
|
+
# Memoize any of our own config, but just return anything outside our tree.
|
91
|
+
if keys.first == CONFIG_ROOT
|
92
|
+
@@memories.bury(*memo_keys, loaded_config)
|
93
|
+
Jekyll.logger.debug(log_key, "Memoizing config: #{@@memories.dig(*memo_keys)}")
|
94
|
+
# And return a config to the caller. Don't return the `new`ly fetched
|
95
|
+
# data directly to ensure consistency between this first fetch and
|
96
|
+
# subsequent memoized fetches, and to let callers take advantage of
|
97
|
+
# the memo Hash's `default_proc` setup.
|
98
|
+
return @@memories.dig(*memo_keys)
|
99
|
+
else
|
100
|
+
return loaded_config
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# AFAICT Ruby::YAML will not give me a Ruby Set[] for a YAML Set,
|
105
|
+
# just a Hash with all-nil-values which is what it is internally.
|
106
|
+
# distorted⇢ image Trying Jekyll _config key: {"(max-width: 400px)"=>nil, "(min-width: 800px)"=>nil, "(min-width: 1500px)"=>nil}
|
107
|
+
# It is possible with some sugar in the YAML files, but I don't
|
108
|
+
# want to ask anyone to do that :)
|
109
|
+
# https://rhnh.net/2011/01/31/yaml-tutorial/
|
110
|
+
def self.set_me_free(dunno)
|
111
|
+
if dunno.class == Array
|
112
|
+
return dunno&.to_set.map{|d| set_me_free(d)}
|
113
|
+
elsif dunno.class == Hash
|
114
|
+
if dunno&.values.all?{|v| v.nil?}
|
115
|
+
return dunno&.keys.to_set
|
116
|
+
else
|
117
|
+
return dunno&.transform_values!{|v| set_me_free(v)}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return dunno
|
121
|
+
end
|
122
|
+
|
123
|
+
# Transform arbitrary configuration data structure keys from
|
124
|
+
# strings to symbols before memoization.
|
125
|
+
# https://stackoverflow.com/a/8189435
|
126
|
+
def self.symbolic(dunno)
|
127
|
+
# Check message-handling responses to gauge emptiness since classes that
|
128
|
+
# don't respond to `:empty?` might not respond to `:method_exists?` either.
|
129
|
+
if dunno.nil?
|
130
|
+
return dunno
|
131
|
+
elsif dunno.class == Hash
|
132
|
+
return dunno.transform_keys!(&:to_sym).transform_values!{|v| symbolic(v)}
|
133
|
+
elsif dunno.class == Array
|
134
|
+
return dunno.map{|r| symbolic(r)}
|
135
|
+
elsif dunno.respond_to?(:to_sym)
|
136
|
+
# Plain types
|
137
|
+
return dunno.to_sym
|
138
|
+
elsif dunno.respond_to?(:to_str)
|
139
|
+
# Freeze string config values.
|
140
|
+
# Specifically :to_str, not :to_s. Usually implemented by actual Strings.
|
141
|
+
return dunno.to_str.freeze
|
142
|
+
end
|
143
|
+
return dunno
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|