distorted-jekyll 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +81 -0
- data/lib/distorted-jekyll/blocks.rb +16 -0
- data/lib/distorted-jekyll/floor.rb +266 -0
- data/lib/distorted-jekyll/invoker.rb +259 -0
- data/lib/distorted-jekyll/md_injection.rb +305 -0
- data/lib/distorted-jekyll/molecule/font.rb +62 -0
- data/lib/distorted-jekyll/molecule/image.rb +94 -0
- data/lib/distorted-jekyll/molecule/lastresort.rb +51 -0
- data/lib/distorted-jekyll/molecule/pdf.rb +79 -0
- data/lib/distorted-jekyll/molecule/svg.rb +47 -0
- data/lib/distorted-jekyll/molecule/text.rb +62 -0
- data/lib/distorted-jekyll/molecule/video.rb +85 -0
- data/lib/distorted-jekyll/monkey_business/jekyll/cleaner.rb +54 -0
- data/lib/distorted-jekyll/static_state.rb +201 -0
- data/lib/distorted-jekyll/template/13th-style.css +79 -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 +32 -34
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/md_injection'
|
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 
|
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,81 @@
|
|
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
|
+
|
25
|
+
distorted:
|
26
|
+
|
27
|
+
# Liquid template caching is default as of Jekyll 4.0,
|
28
|
+
# but it can be disabled if needed.
|
29
|
+
# I just can't think of when it would be needed :)
|
30
|
+
cache_templates: true
|
31
|
+
|
32
|
+
# Should unrecognized media-types fall back to a bare
|
33
|
+
# <img> tag around the original media file?
|
34
|
+
# If not, the site build will fail when an unrecognized
|
35
|
+
# file is encountered.
|
36
|
+
last_resort: true
|
37
|
+
|
38
|
+
# Configure DistorteD format changes by media_type, then by sub_type.
|
39
|
+
# The list of target formats is plain text, media_type/sub_type.
|
40
|
+
# These are mostly based on IANA's official Media Types list:
|
41
|
+
# https://www.iana.org/assignments/media-types/media-types.xhtml
|
42
|
+
# but with some custom additions like using 'gif-sequence' for
|
43
|
+
# animated GIF and leaving 'image/gif' to refer to single-frame GIFs.
|
44
|
+
changes:
|
45
|
+
image:
|
46
|
+
jpeg:
|
47
|
+
? image/jpeg
|
48
|
+
? image/webp
|
49
|
+
png:
|
50
|
+
? image/png
|
51
|
+
? image/webp
|
52
|
+
gif:
|
53
|
+
? image/gif
|
54
|
+
? image/png
|
55
|
+
? image/webp
|
56
|
+
gif-sequence:
|
57
|
+
? image/gif-sequence
|
58
|
+
svg:
|
59
|
+
? image/svg+xml
|
60
|
+
? image/png
|
61
|
+
? image/webp
|
62
|
+
text:
|
63
|
+
plain:
|
64
|
+
? text/plain
|
65
|
+
? image/png
|
66
|
+
? image/webp
|
67
|
+
x-nfo:
|
68
|
+
? text/x-nfo
|
69
|
+
? image/png
|
70
|
+
? image/webp
|
71
|
+
font:
|
72
|
+
ttf:
|
73
|
+
? font/ttf
|
74
|
+
? image/png
|
75
|
+
? image/webp
|
76
|
+
|
77
|
+
outer_limits:
|
78
|
+
image:
|
79
|
+
jpeg: *standard_image
|
80
|
+
png: *standard_image
|
81
|
+
webp: *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,266 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'jekyll'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
require 'distorted/monkey_business/hash'
|
6
|
+
require 'distorted/checking_you_out'
|
7
|
+
|
8
|
+
|
9
|
+
module Jekyll
|
10
|
+
module DistorteD
|
11
|
+
module Floor
|
12
|
+
|
13
|
+
ATTRIBUTES = Set[:lower_world, :changes, :outer_limits]
|
14
|
+
|
15
|
+
# Top-level config key (once stringified) for Jekyll and Default YAML.
|
16
|
+
CONFIG_ROOT = :distorted
|
17
|
+
|
18
|
+
# Filename for default config YAML. Should be a sibling of this file.
|
19
|
+
# Don't move this file or the YAML defaults without changing this.
|
20
|
+
DEFAULT_CONFIG_FILE_NAME = '_config_default.yml'.freeze
|
21
|
+
DEFAULT_CONFIG_PATH = File.join(File.dirname(__FILE__), DEFAULT_CONFIG_FILE_NAME).freeze
|
22
|
+
|
23
|
+
# Separator character for pretty-printing config hierarchy.
|
24
|
+
PP_SEPARATOR = "\u21e2 ".encode('utf-8').freeze
|
25
|
+
|
26
|
+
# Path separator is almost always '/' internally, but support
|
27
|
+
# ALT_SEPARATOR platforms too.
|
28
|
+
# On Lunix - Ruby 2.7:
|
29
|
+
# irb(main):003:0> File::ALT_SEPARATOR
|
30
|
+
# => nil
|
31
|
+
# irb(main):004:0> File::SEPARATOR
|
32
|
+
# => "/"
|
33
|
+
PATH_SEPARATOR = (File::ALT_SEPARATOR || File::SEPARATOR).freeze
|
34
|
+
|
35
|
+
|
36
|
+
# Generic main config-loading function that will search, in order:
|
37
|
+
# - The memoized pre-transformed config data store in-memory.
|
38
|
+
# - Jekyll's Site config, for a passed-in site or for the default site.
|
39
|
+
# - DistorteD's Gem-internal default config YAML.
|
40
|
+
#
|
41
|
+
# Optionally provide a class to be used as a fallback for missing keys.
|
42
|
+
def self.config(*keys, **kw)
|
43
|
+
# Symbolize for our internal representation of the config path.
|
44
|
+
# The Jekyll config and default config are both YAML, so we want string
|
45
|
+
# keys for them. Go ahead and prepend the top-level search key here too.
|
46
|
+
memo_keys = keys.compact.map(&:to_sym).to_set
|
47
|
+
search_keys = keys.compact.map(&:to_s).map(&:freeze)
|
48
|
+
# Pretty print the config path for logging.
|
49
|
+
log_key = search_keys.join(PP_SEPARATOR.to_s).freeze
|
50
|
+
# Initialize memoization class variable as a Hash that will return nil
|
51
|
+
# for any key access that doesn't already contain something.
|
52
|
+
@@memories ||= Hash.new { |h,k| h[k] = h.class.new(&h.default_proc) }
|
53
|
+
# Try to load a memoized config if we can, to skip any filesystem
|
54
|
+
# access and data transformation steps.
|
55
|
+
config = @@memories&.dig(*memo_keys)
|
56
|
+
unless config.nil?
|
57
|
+
if config.is_a?(TrueClass) || config.is_a?(FalseClass)
|
58
|
+
return config
|
59
|
+
elsif config.is_a?(Enumerable)
|
60
|
+
unless config.empty?
|
61
|
+
# Can't check this at the top level because True/FalseClass
|
62
|
+
# don't respond to this message.
|
63
|
+
return config
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# The key isn't memoized. Look for it first in Jekyll's Site config.
|
69
|
+
# Is it even possible to have more than one Site? Support being passed
|
70
|
+
# a `site` object just in case, but taking the first one should be fine.
|
71
|
+
site = kw[:site] || Jekyll.sites.first
|
72
|
+
# Get the config, or nil if the queried config path doesn't exist.
|
73
|
+
loaded_config = site.config.dig(*search_keys)
|
74
|
+
if loaded_config.nil?
|
75
|
+
# The wanted config key didn't exist in the Site config, so let's
|
76
|
+
# try our defaults!
|
77
|
+
# This file will always be small enough for a one-shot read.
|
78
|
+
default_config = YAML.load(File.read(DEFAULT_CONFIG_PATH))
|
79
|
+
loaded_config = default_config.dig(*search_keys)
|
80
|
+
unless loaded_config.nil?
|
81
|
+
Jekyll.logger.debug(['Default', log_key].join(PP_SEPARATOR.to_s).concat(':'.freeze), loaded_config)
|
82
|
+
end
|
83
|
+
else # else Jekyll _config is not nil
|
84
|
+
Jekyll.logger.debug(['_config', log_key].join(PP_SEPARATOR.to_s).concat(':'.freeze), loaded_config)
|
85
|
+
end
|
86
|
+
# Was the desired config key found in the Gem defaults?
|
87
|
+
if loaded_config.nil?
|
88
|
+
# Nope.
|
89
|
+
return nil
|
90
|
+
else
|
91
|
+
# Symbolize any output keys and values, and convert Arrays and Ruby::YAML
|
92
|
+
# Sets-as-Hashes to Ruby stdlib Sets.
|
93
|
+
# Returning a Set instead of an Array should be fine since none of our
|
94
|
+
# configs can (read: should) contain duplicate values for any reason.
|
95
|
+
loaded_config = symbolic(set_me_free(loaded_config))
|
96
|
+
end
|
97
|
+
# Memoize any of our own config, but just return anything outside our tree.
|
98
|
+
if keys.first == CONFIG_ROOT
|
99
|
+
@@memories.bury(*memo_keys, loaded_config)
|
100
|
+
Jekyll.logger.debug(log_key, "Memoizing config: #{@@memories.dig(*memo_keys)}")
|
101
|
+
# And return a config to the caller. Don't return the `new`ly fetched
|
102
|
+
# data directly to ensure consistency between this first fetch and
|
103
|
+
# subsequent memoized fetches, and to let callers take advantage of
|
104
|
+
# the memo Hash's `default_proc` setup.
|
105
|
+
return @@memories.dig(*memo_keys)
|
106
|
+
else
|
107
|
+
return loaded_config
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# AFAICT Ruby::YAML will not give me a Ruby Set[] for a YAML Set,
|
112
|
+
# just a Hash with all-nil-values which is what it is internally.
|
113
|
+
# distorted⇢ image Trying Jekyll _config key: {"(max-width: 400px)"=>nil, "(min-width: 800px)"=>nil, "(min-width: 1500px)"=>nil}
|
114
|
+
# It is possible with some sugar in the YAML files, but I don't
|
115
|
+
# want to ask anyone to do that :)
|
116
|
+
# https://rhnh.net/2011/01/31/yaml-tutorial/
|
117
|
+
def self.set_me_free(dunno)
|
118
|
+
if dunno.class == Array
|
119
|
+
return dunno&.to_set.map{|d| set_me_free(d)}
|
120
|
+
elsif dunno.class == Hash
|
121
|
+
if dunno&.values.all?{|v| v.nil?}
|
122
|
+
return dunno&.keys.to_set
|
123
|
+
else
|
124
|
+
return dunno&.transform_values!{|v| set_me_free(v)}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
return dunno
|
128
|
+
end
|
129
|
+
|
130
|
+
# Transform arbitrary configuration data structure keys from
|
131
|
+
# strings to symbols before memoization.
|
132
|
+
# https://stackoverflow.com/a/8189435
|
133
|
+
def self.symbolic(dunno)
|
134
|
+
# Check message-handling responses to gauge emptiness since classes that
|
135
|
+
# don't respond to `:empty?` might not respond to `:method_exists?` either.
|
136
|
+
if dunno.nil?
|
137
|
+
return dunno
|
138
|
+
elsif dunno.class == Hash
|
139
|
+
return dunno.transform_keys!(&:to_sym).transform_values!{|v| symbolic(v)}
|
140
|
+
elsif dunno.class == Array
|
141
|
+
return dunno.map{|r| symbolic(r)}
|
142
|
+
elsif dunno.respond_to?(:to_sym)
|
143
|
+
# Plain types
|
144
|
+
return dunno.to_sym
|
145
|
+
elsif dunno.respond_to?(:to_str)
|
146
|
+
# Freeze string config values.
|
147
|
+
# Specifically :to_str, not :to_s. Usually implemented by actual Strings.
|
148
|
+
return dunno.to_str.freeze
|
149
|
+
end
|
150
|
+
return dunno
|
151
|
+
end
|
152
|
+
|
153
|
+
# Returns a Set of Arrays of search keys to try in config()
|
154
|
+
def search_keys(*keys)
|
155
|
+
# It's likely that we will get a default argument of [nil]
|
156
|
+
# here due to the output of abstract(:whatever) for unset attrs.
|
157
|
+
keys = keys.compact
|
158
|
+
# If a search key path was given, construct one based
|
159
|
+
# on the MIME::Type union Set between the source media
|
160
|
+
# and the plugged MediaMolecule.
|
161
|
+
if keys.empty? or keys.all?{|k| k.nil?}
|
162
|
+
try_keys = type_mars.map{ |t|
|
163
|
+
# Use only the first part of complex sub_types like 'svg+xml'
|
164
|
+
[t.media_type, t.sub_type.split('+').first].compact
|
165
|
+
}
|
166
|
+
else
|
167
|
+
# Or use a user-provided config path.
|
168
|
+
try_keys = Set[keys]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Loads configuration data telling us how to open certain
|
173
|
+
# types of files.
|
174
|
+
def lower_world(*keys)
|
175
|
+
# Try each set of keys until we find a match
|
176
|
+
for try in search_keys(*keys)
|
177
|
+
tried = Jekyll::DistorteD::Floor::config(
|
178
|
+
Jekyll::DistorteD::Floor::CONFIG_ROOT,
|
179
|
+
:welcome,
|
180
|
+
*try,
|
181
|
+
)
|
182
|
+
# Is the YAML config of the appropriate structure?
|
183
|
+
if tried.is_a?(Hash)
|
184
|
+
# Non-Hashes may not respond to `empty?`
|
185
|
+
unless tried.empty?
|
186
|
+
return tried
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Load configuration telling us what media-types to generate
|
193
|
+
# for any given media-type input.
|
194
|
+
def changes(*keys)
|
195
|
+
out = Set[]
|
196
|
+
# `changes` media-type[sub_type] config will contain information about
|
197
|
+
# what variations output format are desired for what input format,
|
198
|
+
# e.g. {:image => {:jpeg => Set['image/jpeg', 'image/webp']}}
|
199
|
+
# It is not automatically implied that the source format is also
|
200
|
+
# an output format!
|
201
|
+
for try in search_keys(*keys)
|
202
|
+
tried = Jekyll::DistorteD::Floor::config(
|
203
|
+
Jekyll::DistorteD::Floor::CONFIG_ROOT,
|
204
|
+
:changes,
|
205
|
+
*try,
|
206
|
+
)
|
207
|
+
if tried.is_a?(Enumerable) and tried.all?{|t| t.is_a?(String)} and not tried.empty?
|
208
|
+
tried.each{ |t|
|
209
|
+
# MIME::Type.new() won't give us a usable Type object:
|
210
|
+
#
|
211
|
+
# irb> MIME::Types['image/svg+xml'].first.preferred_extension
|
212
|
+
# => "svg"
|
213
|
+
# irb> MIME::Type.new('image/svg+xml').preferred_extension
|
214
|
+
# => nil
|
215
|
+
out.merge(CHECKING::YOU::IN(t))
|
216
|
+
}
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# If the config didn't give us any MIME::Type changes
|
221
|
+
# then we will just output the same type we loaded.
|
222
|
+
if out.empty?
|
223
|
+
return type_mars
|
224
|
+
else
|
225
|
+
return out
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# Loads configuration telling us what variations to generate for any
|
230
|
+
# given type of file, or for an arbitrary key hierarchy.
|
231
|
+
def outer_limits(*keys)
|
232
|
+
out = Set[]
|
233
|
+
# See if any config data exists for each given key hierarchy,
|
234
|
+
# but under the root DistorteD config key.
|
235
|
+
for try in search_keys(*keys)
|
236
|
+
tried = Jekyll::DistorteD::Floor::config(
|
237
|
+
Jekyll::DistorteD::Floor::CONFIG_ROOT,
|
238
|
+
:outer_limits,
|
239
|
+
*try,
|
240
|
+
)
|
241
|
+
|
242
|
+
# Is the YAML config of the appropriate structure?
|
243
|
+
# Merge a shallow copy of it with the Liquid-given attrs.
|
244
|
+
# If we don't take a copy the attrs will be memoized into the config.
|
245
|
+
if tried.is_a?(Enumerable) and tried.all?{|t| t.is_a?(Hash)} and not tried.empty?
|
246
|
+
out.merge(tried.dup.map{ |d| d.merge(@liquid_liquid) })
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# We should output something if the config didn't give us anything.
|
251
|
+
# This is kind of a mess right now with redundancies in the call sites
|
252
|
+
# of things like Molecule::Image. I'll come up with a better general-
|
253
|
+
# purpose fallback solution at some point, but for now this will get
|
254
|
+
# non-Image StaticFiles working with no config :)
|
255
|
+
if out.empty?
|
256
|
+
out << {
|
257
|
+
:tag => :full,
|
258
|
+
}
|
259
|
+
end
|
260
|
+
|
261
|
+
return out
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|