distorted-jekyll 0.5.7 → 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/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
|
-
# 
|
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
|