distorted-jekyll 0.5.7 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/distorted-jekyll.rb +1 -1
- data/lib/distorted-jekyll/_config_default.yml +9 -7
- data/lib/distorted-jekyll/floor.rb +122 -4
- data/lib/distorted-jekyll/invoker.rb +80 -221
- data/lib/distorted-jekyll/{injection_of_love.rb → md_injection.rb} +0 -0
- data/lib/distorted-jekyll/molecule/font.rb +48 -15
- data/lib/distorted-jekyll/molecule/image.rb +11 -22
- data/lib/distorted-jekyll/molecule/lastresort.rb +51 -0
- data/lib/distorted-jekyll/molecule/pdf.rb +42 -51
- data/lib/distorted-jekyll/molecule/svg.rb +9 -21
- data/lib/distorted-jekyll/molecule/text.rb +6 -18
- data/lib/distorted-jekyll/molecule/video.rb +54 -12
- data/lib/distorted-jekyll/static_state.rb +201 -0
- data/lib/distorted-jekyll/template/13th-style.css +1 -0
- metadata +7 -44
- data/lib/distorted-jekyll/error_code.rb +0 -24
- data/lib/distorted-jekyll/molecule/abstract.rb +0 -238
- data/lib/distorted-jekyll/molecule/last-resort.rb +0 -54
- data/lib/distorted-jekyll/static/font.rb +0 -42
- data/lib/distorted-jekyll/static/image.rb +0 -55
- data/lib/distorted-jekyll/static/lastresort.rb +0 -28
- data/lib/distorted-jekyll/static/pdf.rb +0 -53
- data/lib/distorted-jekyll/static/state.rb +0 -141
- data/lib/distorted-jekyll/static/svg.rb +0 -52
- data/lib/distorted-jekyll/static/text.rb +0 -57
- data/lib/distorted-jekyll/static/video.rb +0 -90
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5eaf5c713e61dd6cea6fee1d1cb031b7ec25331e8cdeb9aa79f1ea96c61d94a8
|
4
|
+
data.tar.gz: '068625124864b575107596d9b91761171eecdb76cdaf8f34a66fa37f4d34b69e'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b55e4771aadea12c70adf95995432b4cff70cf0548b06ae76dcb8a55f11de273531a3f2def6be56de9b7043a9f752a6f7d7cc1f66299475409ac269be80dc77
|
7
|
+
data.tar.gz: 4c152988ef67bd5717429578de241169b13f7ffee38cb255979184e2b3cdf4d551d1b50d9c4472ca98bbb9695d8892f09b0b2d9d0e2a02deeeb1dd54d8415f66
|
data/lib/distorted-jekyll.rb
CHANGED
@@ -21,9 +21,6 @@ standard_image: &standard_image
|
|
21
21
|
height: 1500
|
22
22
|
media: "(min-width: 800px)"
|
23
23
|
|
24
|
-
standard_text: &standard_text
|
25
|
-
? image/png
|
26
|
-
? image/webp
|
27
24
|
|
28
25
|
distorted:
|
29
26
|
|
@@ -63,10 +60,17 @@ distorted:
|
|
63
60
|
? image/png
|
64
61
|
? image/webp
|
65
62
|
text:
|
66
|
-
plain:
|
67
|
-
|
63
|
+
plain:
|
64
|
+
? text/plain
|
65
|
+
? image/png
|
66
|
+
? image/webp
|
67
|
+
x-nfo:
|
68
|
+
? text/x-nfo
|
69
|
+
? image/png
|
70
|
+
? image/webp
|
68
71
|
font:
|
69
72
|
ttf:
|
73
|
+
? font/ttf
|
70
74
|
? image/png
|
71
75
|
? image/webp
|
72
76
|
|
@@ -75,5 +79,3 @@ distorted:
|
|
75
79
|
jpeg: *standard_image
|
76
80
|
png: *standard_image
|
77
81
|
webp: *standard_image
|
78
|
-
font:
|
79
|
-
ttf: *standard_image
|
@@ -1,12 +1,16 @@
|
|
1
|
-
require 'distorted/monkey_business/hash'
|
2
1
|
require 'yaml'
|
3
2
|
require 'jekyll'
|
4
3
|
require 'set'
|
5
4
|
|
5
|
+
require 'distorted/monkey_business/hash'
|
6
|
+
require 'distorted/checking_you_out'
|
7
|
+
|
6
8
|
|
7
9
|
module Jekyll
|
8
10
|
module DistorteD
|
9
|
-
|
11
|
+
module Floor
|
12
|
+
|
13
|
+
ATTRIBUTES = Set[:lower_world, :changes, :outer_limits]
|
10
14
|
|
11
15
|
# Top-level config key (once stringified) for Jekyll and Default YAML.
|
12
16
|
CONFIG_ROOT = :distorted
|
@@ -67,14 +71,17 @@ module Jekyll
|
|
67
71
|
site = kw[:site] || Jekyll.sites.first
|
68
72
|
# Get the config, or nil if the queried config path doesn't exist.
|
69
73
|
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
74
|
if loaded_config.nil?
|
72
75
|
# The wanted config key didn't exist in the Site config, so let's
|
73
76
|
# try our defaults!
|
74
77
|
# This file will always be small enough for a one-shot read.
|
75
78
|
default_config = YAML.load(File.read(DEFAULT_CONFIG_PATH))
|
76
79
|
loaded_config = default_config.dig(*search_keys)
|
77
|
-
|
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)
|
78
85
|
end
|
79
86
|
# Was the desired config key found in the Gem defaults?
|
80
87
|
if loaded_config.nil?
|
@@ -143,6 +150,117 @@ module Jekyll
|
|
143
150
|
return dunno
|
144
151
|
end
|
145
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
|
+
|
146
264
|
end
|
147
265
|
end
|
148
266
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# Our custom Exceptions
|
2
|
-
require 'distorted
|
2
|
+
require 'distorted/error_code'
|
3
|
+
|
4
|
+
# MIME::Typer
|
5
|
+
require 'distorted/checking_you_out'
|
3
6
|
|
4
7
|
# Configuration-loading code
|
5
8
|
require 'distorted-jekyll/floor'
|
6
|
-
|
7
|
-
# Configuration data manipulations
|
8
|
-
require 'distorted-jekyll/molecule/abstract'
|
9
|
+
require 'distorted-jekyll/static_state'
|
9
10
|
|
10
11
|
# Media-type drivers
|
11
12
|
require 'distorted-jekyll/molecule/font'
|
@@ -14,7 +15,7 @@ require 'distorted-jekyll/molecule/text'
|
|
14
15
|
require 'distorted-jekyll/molecule/pdf'
|
15
16
|
require 'distorted-jekyll/molecule/svg'
|
16
17
|
require 'distorted-jekyll/molecule/video'
|
17
|
-
require 'distorted-jekyll/molecule/
|
18
|
+
require 'distorted-jekyll/molecule/lastresort'
|
18
19
|
|
19
20
|
# Set.to_hash
|
20
21
|
require 'distorted/monkey_business/set'
|
@@ -29,10 +30,6 @@ require 'shellwords'
|
|
29
30
|
# Set is in stdlib but is not in core.
|
30
31
|
require 'set'
|
31
32
|
|
32
|
-
# MIME Magic 🧙♀️
|
33
|
-
require 'mime/types'
|
34
|
-
require 'ruby-filemagic'
|
35
|
-
|
36
33
|
# I mean, this is why we're here, right?
|
37
34
|
require 'jekyll'
|
38
35
|
|
@@ -44,7 +41,8 @@ module Jekyll
|
|
44
41
|
GEM_ROOT = File.dirname(__FILE__).freeze
|
45
42
|
|
46
43
|
# Mix in config-loading methods.
|
47
|
-
include Jekyll::DistorteD::
|
44
|
+
include Jekyll::DistorteD::Floor
|
45
|
+
include Jekyll::DistorteD::StaticState
|
48
46
|
|
49
47
|
# Enabled media_type drivers. These will be attempted back to front.
|
50
48
|
# TODO: Make this configurable.
|
@@ -57,6 +55,17 @@ module Jekyll
|
|
57
55
|
Jekyll::DistorteD::Molecule::Video,
|
58
56
|
Jekyll::DistorteD::Molecule::Image,
|
59
57
|
]
|
58
|
+
# Reduce the above to a Hash of Sets of MediaMolecules-per-Type, keyed by Type.
|
59
|
+
TYPE_MOLECULES = MEDIA_MOLECULES.reduce(
|
60
|
+
Hash.new{|hash, key| hash[key] = Set[]}
|
61
|
+
) { |types, molecule|
|
62
|
+
if molecule.const_defined?(:LOWER_WORLD)
|
63
|
+
molecule.const_get(:LOWER_WORLD).each { |t|
|
64
|
+
types.update(t => Set[molecule]) { |k,o,n| o.merge(n) }
|
65
|
+
}
|
66
|
+
end
|
67
|
+
types
|
68
|
+
}
|
60
69
|
|
61
70
|
# Any any attr value will get a to_sym if shorter than this
|
62
71
|
# totally arbitrary length, or if the attr key is in the plugged
|
@@ -80,10 +89,21 @@ module Jekyll
|
|
80
89
|
# Filename is the only non-keyword argument our tag should ever get.
|
81
90
|
# It's spe-shul and gets its own definition outside the attr loop.
|
82
91
|
if parsed_arguments.key?(:src)
|
83
|
-
@name = parsed_arguments
|
92
|
+
@name = parsed_arguments.delete(:src)
|
84
93
|
else
|
85
|
-
@name = parsed_arguments
|
94
|
+
@name = parsed_arguments.delete(:argv1)
|
86
95
|
end
|
96
|
+
@liquid_liquid = parsed_arguments.select{ |attr, val|
|
97
|
+
not [nil, ''.freeze].include?(val)
|
98
|
+
}.transform_keys { |attr|
|
99
|
+
attr.length <= ARBITRARY_ATTR_SYMBOL_STRING_LENGTH_BOUNDARY ? attr.to_sym : attr.freeze
|
100
|
+
}.transform_values { |val|
|
101
|
+
if val.respond_to?(:length)
|
102
|
+
val.length <= ARBITRARY_ATTR_SYMBOL_STRING_LENGTH_BOUNDARY ? val.to_sym : val.freeze
|
103
|
+
else
|
104
|
+
val
|
105
|
+
end
|
106
|
+
}
|
87
107
|
|
88
108
|
# If we didn't get one of the two above options there is nothing we
|
89
109
|
# can do but bail.
|
@@ -91,173 +111,46 @@ module Jekyll
|
|
91
111
|
raise "Failed to get a usable filename from #{arguments}"
|
92
112
|
end
|
93
113
|
|
94
|
-
|
95
|
-
# `distorted IIDX-Readers-Unboxing.jpg: [#<MIME::Type: image/jpeg>]`
|
96
|
-
#
|
97
|
-
# Types#type_for can return multiple possibilities for a filename.
|
98
|
-
# For example, an XML file: [application/xml, text/xml].
|
99
|
-
mime = MIME::Types.type_for(@name).to_set
|
100
|
-
|
101
|
-
# We can't proceed without a usable media type.
|
102
|
-
# Look at the actual file iff the filename wasn't enough to guess.
|
103
|
-
unless mime.empty?
|
104
|
-
Jekyll.logger.debug(@tag_name, "Detected #{@name} media types: #{mime}")
|
105
|
-
else
|
106
|
-
# Did we fail to guess any MIME::Types from the given filename?
|
107
|
-
# We're going to have to look at the actual file
|
108
|
-
# (or at least its first four bytes).
|
109
|
-
# `@mime` will be readable/writable in the FileMagic.open block context
|
110
|
-
# since it was already defined in the outer scope.
|
111
|
-
FileMagic.open(:mime) do |fm|
|
112
|
-
# TODO: Support finding files in paths deeper than the Site source.
|
113
|
-
# There's no good way to get the path here of the Markdown file
|
114
|
-
# that included our Tag, so relative paths won't work if given
|
115
|
-
# as just a filename. It should work if supplied like:
|
116
|
-
# ![The coolest image ever](/2020/04/20/some-post/hahanofileextension)
|
117
|
-
# This limitation is normally not a problem since we can guess
|
118
|
-
# the MIME::Types just based on the filename.
|
119
|
-
# It would be possible to supply the Markdown document's path
|
120
|
-
# as an additional argument to {% distorted %} when converting
|
121
|
-
# Markdown in `injection_of_love`, but I am resisting that
|
122
|
-
# approach because it would make DD's Liquid and Markdown entrypoints
|
123
|
-
# no longer exactly equivalent, and that's not okay with me.
|
124
|
-
test_path = File.join(
|
125
|
-
Jekyll::DistorteD::Floor::config(:source),
|
126
|
-
Jekyll::DistorteD::Floor::config(:collections_dir),
|
127
|
-
@name,
|
128
|
-
)
|
129
|
-
# The second argument makes fm.file return just the simple
|
130
|
-
# MIME::Type String, e.g.:
|
131
|
-
#
|
132
|
-
# irb(main):006:1* fm.file('/home/okeeblow/IIDX-turntable.svg')
|
133
|
-
# => "image/svg+xml; charset=us-ascii"
|
134
|
-
# irb(main):009:1* fm.file('/home/okeeblow/IIDX-turntable.svg', true)
|
135
|
-
# => "image/svg"
|
136
|
-
#
|
137
|
-
# However MIME::Types won't take short variants like 'image/svg',
|
138
|
-
# so explicitly have FM return long types and split it ourself
|
139
|
-
# on the semicolon:
|
140
|
-
#
|
141
|
-
# irb(main):038:0> "image/svg+xml; charset=us-ascii".split(';').first
|
142
|
-
# => "image/svg+xml"
|
143
|
-
mime = Set[MIME::Types[fm.file(@name, false).split(';'.freeze).first]]
|
144
|
-
end
|
114
|
+
end
|
145
115
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
116
|
+
# Returns a Set of DD MIME::Types descriving our file,
|
117
|
+
# optionally falling through to a plain file copy.
|
118
|
+
def type_mars
|
119
|
+
@type_mars ||= begin
|
120
|
+
mime = CHECKING::YOU::OUT(@name)
|
121
|
+
if mime.empty?
|
122
|
+
if Jekyll::DistorteD::Floor::config(Jekyll::DistorteD::Floor::CONFIG_ROOT, :last_resort)
|
123
|
+
mime = Jekyll::DistorteD::Molecule::LastResort::LOWER_WORLD
|
153
124
|
end
|
154
125
|
end
|
126
|
+
mime
|
155
127
|
end
|
128
|
+
end
|
156
129
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
# Take the union of this file's detected MIME::Types and
|
164
|
-
# the supported MEDIA_TYPES declared in each molecule.
|
165
|
-
# Molecules will likely declare their Types with a regex:
|
166
|
-
# https://rdoc.info/gems/mime-types/MIME%2FTypes:[]
|
167
|
-
#
|
168
|
-
#
|
169
|
-
# Still-Image Mime::Types Example:
|
170
|
-
# MIME::Types.type_for('IIDX-Readers-Unboxing.jpg')
|
171
|
-
# => [#<MIME::Type: image/jpeg>]
|
172
|
-
#
|
173
|
-
# Video MIME::Types Example:
|
174
|
-
# MIME::Types.type_for('play.mp4') => [
|
175
|
-
# #<MIME::Type: application/mp4>,
|
176
|
-
# #<MIME::Type: audio/mp4>,
|
177
|
-
# #<MIME::Type: video/mp4>,
|
178
|
-
# #<MIME::Type: video/vnd.objectvideo>
|
179
|
-
# ]
|
180
|
-
#
|
181
|
-
#
|
182
|
-
# Molecule declared-supported MIME::Types Example:
|
183
|
-
# (huge list)
|
184
|
-
# MIME_TYPES = MIME::Types[/^#{MEDIA_TYPE}/, :complete => true]
|
185
|
-
#
|
186
|
-
#
|
187
|
-
# Detected & Declared MIME::Types Union Example:
|
188
|
-
# MIME::Types.type_for('play.mp4') & MIME::Types[/^video/, :complete => true]
|
189
|
-
# => [#<MIME::Type: video/mp4>, #<MIME::Type: video/vnd.objectvideo>]
|
190
|
-
#
|
191
|
-
# ^ This non-empty example union means we sould try this driver for this file.
|
192
|
-
#
|
193
|
-
#
|
194
|
-
# Loop until we've found a match or tried all available drivers.
|
195
|
-
loop do
|
196
|
-
# Attempt to plug the last driver in the array of enabled drivers.
|
197
|
-
molecule = media_molecules.pop
|
198
|
-
|
199
|
-
# This will be nil once we've tried them all and run out and are on the last loop.
|
200
|
-
if molecule == nil
|
201
|
-
if Jekyll::DistorteD::Floor::config(self.class.const_get(:CONFIG_ROOT), :last_resort)
|
202
|
-
Jekyll.logger.debug(@tag_name, "Falling back to a bare <img> for #{name}")
|
203
|
-
@mime = Jekyll::DistorteD::Molecule::LastResort::MIME_TYPES
|
204
|
-
molecule = Jekyll::DistorteD::Molecule::LastResort
|
205
|
-
else
|
206
|
-
raise MediaTypeNotImplementedError.new(@name)
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
Jekyll.logger.debug(@tag_name, "Trying to plug #{@name} into #{molecule}")
|
211
|
-
|
212
|
-
# We found a potentially-compatible driver iff the union set is non-empty.
|
213
|
-
if not (mime & molecule.const_get(:MIME_TYPES)).empty?
|
214
|
-
@mime = mime & molecule.const_get(:MIME_TYPES)
|
215
|
-
Jekyll.logger.debug(@tag_name, "Enabling #{molecule} for #{@name}: #{mime}")
|
216
|
-
|
217
|
-
# Override Invoker's stubs by prepending the driver's methods to our DD instance's singleton class.
|
218
|
-
# https://devalot.com/articles/2008/09/ruby-singleton
|
219
|
-
# `self.singleton_class.extend(molecule)` doesn't work in this context.
|
220
|
-
self.singleton_class.instance_variable_set(:@media_molecule, molecule)
|
221
|
-
|
222
|
-
# Set instance variables for the combined set of HTML element
|
223
|
-
# attributes used for this media_type. The global set is defined in this file
|
224
|
-
# (Invoker), and the media_type-specific set is appended to that during auto-plug.
|
225
|
-
attrs = (self.singleton_class.const_get(:GLOBAL_ATTRS) + molecule.const_get(:ATTRS)).to_hash
|
226
|
-
attrs.each_pair do |attr, val|
|
227
|
-
# An attr supplied to the Liquid tag should override any from the config
|
228
|
-
liquid_val = parsed_arguments&.dig(attr)
|
229
|
-
# nil.to_s is '', so print 'nil' for readability.
|
230
|
-
Jekyll.logger.debug("Liquid #{attr}", liquid_val || 'nil')
|
231
|
-
|
232
|
-
if liquid_val.is_a?(String)
|
233
|
-
# Symbolize String values of any attr that has a Molecule-defined list
|
234
|
-
# of acceptable values, or — completely arbitrarily — any String value
|
235
|
-
# shorter than an arbitrarily-chosen constant.
|
236
|
-
# Otherwise freeze them.
|
237
|
-
if (liquid_val.length <= ARBITRARY_ATTR_SYMBOL_STRING_LENGTH_BOUNDARY) or
|
238
|
-
molecule.const_get(:ATTRS_VALUES).key?(attr)
|
239
|
-
liquid_val = liquid_val&.to_sym
|
240
|
-
elsif liquid_val.length > ARBITRARY_ATTR_SYMBOL_STRING_LENGTH_BOUNDARY
|
241
|
-
# Will be default in Ruby 3.
|
242
|
-
liquid_val = liquid_val&.freeze
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
attrs[attr] = liquid_val
|
247
|
-
end
|
248
|
-
|
249
|
-
# Save attrs to our instance as the data source for Molecule::Abstract.attrs.
|
250
|
-
@attrs = attrs
|
251
|
-
|
252
|
-
# Plug the chosen Media Molecule!
|
253
|
-
# Using Module#prepend puts the Molecule's ahead in the ancestor chain
|
254
|
-
# of any defined here, or any defined in an `include`d module.
|
255
|
-
(class <<self; prepend @media_molecule; end)
|
130
|
+
# Return any arguments given by the user to our Liquid tag.
|
131
|
+
# This method name is generic across all DD entrypoints so it can be
|
132
|
+
# referenced from lower layers in the pile.
|
133
|
+
def user_arguments
|
134
|
+
@liquid_liquid || Hash[]
|
135
|
+
end
|
256
136
|
|
257
|
-
|
258
|
-
|
259
|
-
|
137
|
+
# Decides which MediaMolecule is most appropriate for our file and returns it.
|
138
|
+
def media_molecule
|
139
|
+
available_molecules = TYPE_MOLECULES.keys.to_set & type_mars
|
140
|
+
# TODO: Handle multiple molecules for the same file
|
141
|
+
case available_molecules.length
|
142
|
+
when 0
|
143
|
+
raise MediaTypeNotImplementedError.new(@name)
|
144
|
+
when 1
|
145
|
+
return TYPE_MOLECULES[available_molecules.first].first
|
146
|
+
end
|
147
|
+
end
|
260
148
|
|
149
|
+
def plug
|
150
|
+
unless self.singleton_class.instance_variable_defined?(:@media_molecule)
|
151
|
+
self.singleton_class.instance_variable_set(:@media_molecule, media_molecule)
|
152
|
+
self.singleton_class.prepend(media_molecule)
|
153
|
+
Jekyll.logger.info(@name, "Plugging #{media_molecule}")
|
261
154
|
end
|
262
155
|
end
|
263
156
|
|
@@ -265,16 +158,18 @@ module Jekyll
|
|
265
158
|
# https://github.com/jekyll/jekyll/blob/HEAD/lib/jekyll/renderer.rb
|
266
159
|
# https://jekyllrb.com/tutorials/orderofinterpretation/
|
267
160
|
def render(context)
|
161
|
+
plug
|
268
162
|
render_to_output_buffer(context, '')
|
269
163
|
end
|
270
164
|
|
271
165
|
# A future Liquid version (5.0?) will call this function directly
|
272
166
|
# instead of calling render()
|
273
167
|
def render_to_output_buffer(context, output)
|
168
|
+
plug
|
274
169
|
# Get Jekyll Site object back from tag rendering context registers so we
|
275
170
|
# can get configuration data and path information from it and
|
276
171
|
# then pass it along to our StaticFile subclass.
|
277
|
-
site = context.registers[:site]
|
172
|
+
@site = context.registers[:site]
|
278
173
|
|
279
174
|
# The rendering context's `first` page will be the one that invoked us.
|
280
175
|
page_data = context.environments.first['page'.freeze]
|
@@ -282,12 +177,12 @@ module Jekyll
|
|
282
177
|
#
|
283
178
|
# Our subclass' additional args:
|
284
179
|
# dest - The String path to the generated `url` folder of the page HTML output
|
285
|
-
base = site.source
|
180
|
+
@base = @site.source
|
286
181
|
|
287
182
|
# `relative_path` doesn't seem to always exist, but `path` does? idk.
|
288
183
|
# I was testing with `relative_path` only with `_posts`, but it broke
|
289
184
|
# when I invoked DD on a _page. Both have `path`.
|
290
|
-
dir = File.dirname(page_data['path'.freeze])
|
185
|
+
@dir = File.dirname(page_data['path'.freeze])
|
291
186
|
|
292
187
|
# Every one of Ruby's `File.directory?` / `Pathname.directory?` /
|
293
188
|
# `FileTest.directory?` methods actually tests that path on the
|
@@ -298,67 +193,30 @@ module Jekyll
|
|
298
193
|
# directory (like configured on cooltrainer) or a `.html`
|
299
194
|
# (or other extension) like the default Jekyll config.
|
300
195
|
# Get the dirname if the url is not a dir itself.
|
301
|
-
@
|
302
|
-
unless @
|
303
|
-
@
|
196
|
+
@relative_dest = page_data['url'.freeze]
|
197
|
+
unless @relative_dest[-1] == Jekyll::DistorteD::Floor::PATH_SEPARATOR
|
198
|
+
@relative_dest = File.dirname(@relative_dest)
|
304
199
|
# Append the trailing slash so we don't have to do it
|
305
200
|
# in the Liquid templates.
|
306
|
-
@
|
201
|
+
@relative_dest << Jekyll::DistorteD::Floor::PATH_SEPARATOR
|
307
202
|
end
|
308
203
|
|
309
|
-
# Create an instance of the media-appropriate Jekyll::StaticFile subclass.
|
310
|
-
#
|
311
|
-
# StaticFile args:
|
312
|
-
# site - The Jekyll Site object.
|
313
|
-
# base - The String path to the Jekyll::Site.source, e.g. /home/okeeblow/Works/cooltrainer
|
314
|
-
# dir - The String path between <base> and the source file, e.g. _posts/2018-10-15-super-cool-post
|
315
|
-
# name - The String filename of the original media, e.g. cool.jpg
|
316
|
-
# mime - The Set of MIME::Types of the original media.
|
317
|
-
# attrs - The Set of attributes given to our Liquid tag, if any.
|
318
|
-
# dd_dest - The String path under Site.dest to DD's top-level media output directory.
|
319
|
-
# url - The URL of the page this tag is on.
|
320
|
-
static_file = self.static_file(
|
321
|
-
site,
|
322
|
-
base,
|
323
|
-
dir,
|
324
|
-
@name,
|
325
|
-
@mime,
|
326
|
-
@attrs,
|
327
|
-
@dd_dest,
|
328
|
-
@url,
|
329
|
-
)
|
330
|
-
|
331
204
|
# Add our new file to the list that will be handled
|
332
205
|
# by Jekyll's built-in StaticFile generator.
|
333
|
-
|
334
|
-
|
335
|
-
site.static_files << static_file
|
336
|
-
end
|
337
|
-
|
338
|
-
# Called by a Molecule-specific render() method since they will
|
339
|
-
# all load their Liquid template files in the same way.
|
340
|
-
# Bail out if this is not handled by the module we just mixed in.
|
341
|
-
# Any media Molecule must override this to return an instance of
|
342
|
-
# their media-type-appropriate StaticFile subclass.
|
343
|
-
def static_file(site, base, dir, name, mime, attrs, dd_dest, url)
|
344
|
-
raise MediaTypeNotImplementedError.new(name)
|
206
|
+
@site.static_files << self
|
207
|
+
output
|
345
208
|
end
|
346
209
|
|
347
210
|
# Generic Liquid template loader that will be used in every MediaMolecule.
|
348
211
|
# Callers will call `render(**{:template => vars})` on the Object returned
|
349
212
|
# by this method.
|
350
213
|
def parse_template(site: nil, name: nil)
|
351
|
-
site = site || Jekyll.sites.first
|
214
|
+
site = site || @site || Jekyll.sites.first
|
352
215
|
begin
|
353
216
|
# Use a given filename, or detect one based on media-type.
|
354
217
|
if name.nil?
|
355
|
-
#
|
356
|
-
|
357
|
-
if self.singleton_class.const_defined?(:SUB_TYPE)
|
358
|
-
name = "#{self.singleton_class.const_get(:SUB_TYPE)}.liquid".freeze
|
359
|
-
else
|
360
|
-
name = "#{self.singleton_class.const_get(:MEDIA_TYPE)}.liquid".freeze
|
361
|
-
end
|
218
|
+
# e.g. Jekyll::DistorteD::Molecule::Image -> 'image.liquid'
|
219
|
+
name = "#{self.singleton_class.instance_variable_get(:@media_molecule).name.gsub(/^.*::/, '').downcase}.liquid".freeze
|
362
220
|
elsif not name.include?('.liquid'.freeze)
|
363
221
|
# Support filename arguments with and without file extension.
|
364
222
|
# The given String might already be frozen, so concatenating
|
@@ -395,6 +253,7 @@ module Jekyll
|
|
395
253
|
end
|
396
254
|
end # parse_template
|
397
255
|
|
256
|
+
|
398
257
|
end
|
399
258
|
end
|
400
259
|
end
|