distorted-jekyll 0.5.6 → 0.5.7
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 +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
@@ -0,0 +1,238 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
require 'distorted-jekyll/floor'
|
4
|
+
|
5
|
+
require 'jekyll'
|
6
|
+
require 'liquid/errors'
|
7
|
+
require 'liquid/template'
|
8
|
+
require 'mime/types'
|
9
|
+
|
10
|
+
|
11
|
+
module Jekyll
|
12
|
+
module DistorteD
|
13
|
+
module Molecule
|
14
|
+
module Abstract
|
15
|
+
|
16
|
+
# This list should contain global attributes only, as symbols.
|
17
|
+
# The final attribute set will be this + the media-type-specific set.
|
18
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes
|
19
|
+
GLOBAL_ATTRS = Set[:title]
|
20
|
+
|
21
|
+
|
22
|
+
# Returns a Set of Arrays of search keys to try in config()
|
23
|
+
def search_keys(*keys)
|
24
|
+
# It's likely that we will get a default argument of [nil]
|
25
|
+
# here due to the output of attr_value(:whatever) for unset attrs.
|
26
|
+
keys = keys.compact
|
27
|
+
# If a search key path was given, construct one based
|
28
|
+
# on the MIME::Type union Set between the source media
|
29
|
+
# and the plugged MediaMolecule.
|
30
|
+
if keys.empty? or keys.all?{|k| k.nil?}
|
31
|
+
try_keys = @mime.map{ |t|
|
32
|
+
# Use only the first part of complex sub_types like 'svg+xml'
|
33
|
+
[t.media_type, t.sub_type.split('+').first].compact
|
34
|
+
}
|
35
|
+
else
|
36
|
+
# Or use a user-provided config path.
|
37
|
+
try_keys = Set[keys]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Loads configuration data telling us how to open certain
|
42
|
+
# types of files.
|
43
|
+
def welcome(*keys)
|
44
|
+
# Try each set of keys until we find a match
|
45
|
+
for try in search_keys(*keys)
|
46
|
+
tried = Jekyll::DistorteD::Floor::config(
|
47
|
+
Jekyll::DistorteD::Floor::CONFIG_ROOT,
|
48
|
+
:welcome,
|
49
|
+
*try,
|
50
|
+
)
|
51
|
+
# Is the YAML config of the appropriate structure?
|
52
|
+
if tried.is_a?(Hash)
|
53
|
+
# Non-Hashes may not respond to `empty?`
|
54
|
+
unless tried.empty?
|
55
|
+
return tried
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Load configuration telling us what media-types to generate
|
62
|
+
# for any given media-type input.
|
63
|
+
def changes(*keys)
|
64
|
+
out = Set[]
|
65
|
+
# `changes` media-type[sub_type] config will contain information about
|
66
|
+
# what variations output format are desired for what input format,
|
67
|
+
# e.g. {:image => {:jpeg => Set['image/jpeg', 'image/webp']}}
|
68
|
+
# It is not automatically implied that the source format is also
|
69
|
+
# an output format!
|
70
|
+
for try in search_keys(*keys)
|
71
|
+
tried = Jekyll::DistorteD::Floor::config(
|
72
|
+
Jekyll::DistorteD::Floor::CONFIG_ROOT,
|
73
|
+
:changes,
|
74
|
+
*try,
|
75
|
+
)
|
76
|
+
if tried.is_a?(Enumerable) and tried.all?{|t| t.is_a?(String)} and not tried.empty?
|
77
|
+
tried.each{ |t|
|
78
|
+
# MIME::Type.new() won't give us a usable Type object:
|
79
|
+
#
|
80
|
+
# irb> MIME::Types['image/svg+xml'].first.preferred_extension
|
81
|
+
# => "svg"
|
82
|
+
# irb> MIME::Type.new('image/svg+xml').preferred_extension
|
83
|
+
# => nil
|
84
|
+
out.merge(MIME::Types[t])
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# If the config didn't give us any MIME::Type changes
|
90
|
+
# then we will just output the same type we loaded.
|
91
|
+
if out.empty?
|
92
|
+
return @mime
|
93
|
+
else
|
94
|
+
return out
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Loads configuration telling us what variations to generate for any
|
99
|
+
# given type of file, or for an arbitrary key hierarchy.
|
100
|
+
def outer_limits(*keys)
|
101
|
+
out = Set[]
|
102
|
+
# See if any config data exists for each given key hierarchy,
|
103
|
+
# but under the root DistorteD config key.
|
104
|
+
for try in search_keys(*keys)
|
105
|
+
tried = Jekyll::DistorteD::Floor::config(
|
106
|
+
Jekyll::DistorteD::Floor::CONFIG_ROOT,
|
107
|
+
:outer_limits,
|
108
|
+
*try,
|
109
|
+
)
|
110
|
+
|
111
|
+
# Is the YAML config of the appropriate structure?
|
112
|
+
# Merge a shallow copy of it with the Liquid-given attrs.
|
113
|
+
# If we don't take a copy the attrs will be memoized into the config.
|
114
|
+
if tried.is_a?(Enumerable) and tried.all?{|t| t.is_a?(Hash)} and not tried.empty?
|
115
|
+
out.merge(tried.dup.map{ |d| d.merge(attrs) })
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# We should output something if the config didn't give us anything.
|
120
|
+
# This is kind of a mess right now with redundancies in the call sites
|
121
|
+
# of things like Molecule::Image. I'll come up with a better general-
|
122
|
+
# purpose fallback solution at some point, but for now this will get
|
123
|
+
# non-Image StaticFiles working with no config :)
|
124
|
+
if out.empty?
|
125
|
+
out << {
|
126
|
+
:tag => :full,
|
127
|
+
:crop => :none,
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
return out
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns a Hash of any attribute provided to DD's Liquid tag and its value.
|
135
|
+
def attrs
|
136
|
+
# Value of every Molecule-defined attr will be nil if that attr
|
137
|
+
# is not provided to our Liquid tag.
|
138
|
+
@attrs.keep_if{|attr,val| val != nil}
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns the value for an attribute as given to the Liquid tag,
|
142
|
+
# the default value if the given value is not in the accepted Set,
|
143
|
+
# or nil for unset attrs with no default defined.
|
144
|
+
def attr_value(attribute)
|
145
|
+
# Set of all supported attributes:
|
146
|
+
# - Global output-element attributes
|
147
|
+
# - Molecule-specific output-element attributes
|
148
|
+
# - Filetype change and output-template config paths
|
149
|
+
accepted_attrs = self.singleton_class.const_get(:GLOBAL_ATTRS) + self.singleton_class.const_get(:ATTRS) + Set[:changes, :outer_limits]
|
150
|
+
|
151
|
+
# Set of acceptable values for the given attribute, e.g. Image::loading => Set[:eager, :lazy]
|
152
|
+
# Will be empty if this attribute takes freeform input (like `title` or `alt`)
|
153
|
+
accepted_vals = self.singleton_class.const_get(:ATTRS_VALUES)&.dig(attribute)
|
154
|
+
|
155
|
+
# The value, if any, provided to our Liquid tag for this attr.
|
156
|
+
liquid_val = attrs&.dig(attribute)
|
157
|
+
|
158
|
+
# Is the requested attribute name defined as an accepted attribute
|
159
|
+
# either globally or within the plugged MediaMolecule?
|
160
|
+
if accepted_attrs.include?(attribute.to_sym)
|
161
|
+
|
162
|
+
# Does this attr define a set of acceptable values?
|
163
|
+
if accepted_vals.is_a?(Set)
|
164
|
+
# Yes, it does. Is the Liquid-given value in that Set of acceptable values?
|
165
|
+
if accepted_vals.include?(liquid_val) or accepted_vals.include?(liquid_val&.to_sym) or accepted_vals.include?(liquid_val&.to_s)
|
166
|
+
|
167
|
+
# Yes, it is! Use it.
|
168
|
+
liquid_val.to_s
|
169
|
+
else
|
170
|
+
# No, it isn't. Warn and return the default.
|
171
|
+
unless liquid_val.nil?
|
172
|
+
Jekyll.logger.warn('DistorteD', "#{liquid_val.to_s} is not an acceptable value for #{attribute.to_s}: #{accepted_vals}")
|
173
|
+
end
|
174
|
+
self.singleton_class.const_get(:ATTRS_DEFAULT)&.dig(attribute).to_s
|
175
|
+
end
|
176
|
+
elsif accepted_vals.is_a?(Regexp)
|
177
|
+
if accepted_vals =~ liquid_val.to_s
|
178
|
+
liquid_val.to_s
|
179
|
+
else
|
180
|
+
unless liquid_val.nil?
|
181
|
+
Jekyll.logger.warn('DistorteD', "#{liquid_val.to_s} is not a Regexp match for #{attribute.to_s}: #{accepted_vals}")
|
182
|
+
end
|
183
|
+
self.singleton_class.const_get(:ATTRS_DEFAULT)&.dig(attribute)
|
184
|
+
end
|
185
|
+
else
|
186
|
+
# No, this attribute does not define a Set of acceptable values.
|
187
|
+
# The freeform Liquid-given value is fine, but if it's nil
|
188
|
+
# we can still try for a default.
|
189
|
+
if liquid_val.nil?
|
190
|
+
self.singleton_class.const_get(:ATTRS_DEFAULT)&.dig(attribute)
|
191
|
+
else
|
192
|
+
liquid_val
|
193
|
+
end
|
194
|
+
end
|
195
|
+
else
|
196
|
+
Jekyll.logger.error('DistorteD', "#{attribute.to_s} is not a supported attribute")
|
197
|
+
nil
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns a Hash keyed by MIME::Type objects with value as a Set of Hashes
|
202
|
+
# describing the media's output variations to be generated for each Type.
|
203
|
+
def variations
|
204
|
+
changes(attr_value(:changes)).map{ |t|
|
205
|
+
[t, outer_limits(attr_value(:outer_limits)).map{ |d|
|
206
|
+
d.merge({
|
207
|
+
# e.g. 'SomeImage-medium.jpg` but just `SomeImage.jpg` and not `SomeImage-full.jpg`
|
208
|
+
# for the full-resolution outputs.
|
209
|
+
# The default `.jpeg` preferred_extension is monkey-patched to `.jpg` because lol
|
210
|
+
:name => "#{File.basename(@name, '.*')}#{'-'.concat(d&.dig(:tag).to_s) if d&.dig(:tag) != :full}.#{t.preferred_extension}",
|
211
|
+
})
|
212
|
+
}]
|
213
|
+
}.to_h
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns a flat Set of Hashes that each describe one variant of
|
217
|
+
# media file output that should exist for a given input file.
|
218
|
+
def files
|
219
|
+
filez = Set[]
|
220
|
+
variations.each_pair{ |t,v|
|
221
|
+
# Merge the type in to each variation Hash since we will no longer
|
222
|
+
# have it as the key to this Set in its container Hash.
|
223
|
+
v.each{ |d| filez.add(d.merge({:type => t})) }
|
224
|
+
}
|
225
|
+
filez
|
226
|
+
end
|
227
|
+
|
228
|
+
# Returns a Set of just the String filenames we want for this media.
|
229
|
+
# This will be used by `modified?` among others.
|
230
|
+
def filenames
|
231
|
+
files.map{|f| f[:name]}.to_set
|
232
|
+
end
|
233
|
+
|
234
|
+
|
235
|
+
end # Abstract
|
236
|
+
end # Molecule
|
237
|
+
end # DistorteD
|
238
|
+
end # Jekyll
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
require 'distorted-jekyll/molecule/text'
|
4
|
+
require 'distorted-jekyll/static/font'
|
5
|
+
|
6
|
+
module Jekyll
|
7
|
+
module DistorteD
|
8
|
+
module Molecule
|
9
|
+
module Font
|
10
|
+
|
11
|
+
include Text
|
12
|
+
|
13
|
+
DRIVER = Cooltrainer::DistorteD::Font
|
14
|
+
|
15
|
+
MEDIA_TYPE = DRIVER::MEDIA_TYPE
|
16
|
+
MIME_TYPES = DRIVER::MIME_TYPES
|
17
|
+
|
18
|
+
ATTRS = DRIVER::ATTRS
|
19
|
+
ATTRS_DEFAULT = DRIVER::ATTRS_DEFAULT
|
20
|
+
ATTRS_VALUES = DRIVER::ATTRS_VALUES
|
21
|
+
|
22
|
+
|
23
|
+
def static_file(*args)
|
24
|
+
Jekyll::DistorteD::Static::Font.new(*args)
|
25
|
+
end
|
26
|
+
end # Font
|
27
|
+
end # Molecule
|
28
|
+
end # DistorteD
|
29
|
+
end # Jekyll
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
require 'distorted/image'
|
4
|
+
require 'distorted-jekyll/static/image'
|
5
|
+
|
6
|
+
module Jekyll
|
7
|
+
module DistorteD
|
8
|
+
module Molecule
|
9
|
+
module Image
|
10
|
+
|
11
|
+
# Reference these instead of reassigning them. Consistency is mandatory.
|
12
|
+
MEDIA_TYPE = Cooltrainer::DistorteD::Image::MEDIA_TYPE
|
13
|
+
MIME_TYPES = Cooltrainer::DistorteD::Image::MIME_TYPES
|
14
|
+
|
15
|
+
ATTRS = Cooltrainer::DistorteD::Image::ATTRS
|
16
|
+
ATTRS_DEFAULT = Cooltrainer::DistorteD::Image::ATTRS_DEFAULT
|
17
|
+
ATTRS_VALUES = Cooltrainer::DistorteD::Image::ATTRS_VALUES
|
18
|
+
|
19
|
+
|
20
|
+
# Returns the filename we should use in the oldschool <img> tag
|
21
|
+
# as a fallback for <picture> sources. This file should be a cropped
|
22
|
+
# variation, the same MIME::Type as the input media, with the largest
|
23
|
+
# resolution possible.
|
24
|
+
# Failing that, use the filename of the original media.
|
25
|
+
# TODO: Handle situations when the input media_type is not in the
|
26
|
+
# Set of output media_types. We should pick the largest cropped variation
|
27
|
+
# of any type in that case.
|
28
|
+
def fallback_img
|
29
|
+
biggest_ver = nil
|
30
|
+
|
31
|
+
# Computes a Set of non-nil MIME::Type.sub_types for all MIME::Types
|
32
|
+
# detected for the original media file.
|
33
|
+
sub_types = @mime.keep_if{ |m|
|
34
|
+
m.media_type == self.singleton_class.const_get(:MEDIA_TYPE)
|
35
|
+
}.map { |m|
|
36
|
+
m.sub_type
|
37
|
+
}.compact.to_set
|
38
|
+
files.keep_if{|f| f.key?(:width) or f.key?(:height)}.each{ |f|
|
39
|
+
if sub_types.include?(f[:type]&.sub_type)
|
40
|
+
if biggest_ver
|
41
|
+
if f[:width] > biggest_ver[:width]
|
42
|
+
biggest_ver = f
|
43
|
+
end
|
44
|
+
else
|
45
|
+
biggest_ver = f
|
46
|
+
end
|
47
|
+
end
|
48
|
+
}
|
49
|
+
# Return the filename of the biggest matched variation,
|
50
|
+
# otherwise use the original filename.
|
51
|
+
biggest_ver&.dig(:name) || @name
|
52
|
+
end
|
53
|
+
|
54
|
+
def outer_limits(*keys)
|
55
|
+
config = super
|
56
|
+
if config.empty?
|
57
|
+
Set[{
|
58
|
+
tag: :full,
|
59
|
+
crop: :none,
|
60
|
+
}]
|
61
|
+
else
|
62
|
+
config
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def render_to_output_buffer(context, output)
|
67
|
+
super
|
68
|
+
begin
|
69
|
+
# Liquid doesn't seem able to reference symbolic keys,
|
70
|
+
# so convert everything to string for template.
|
71
|
+
# Remove full-size images from <sources> list before generating.
|
72
|
+
# Those should only be linked to, not displayed.
|
73
|
+
filez = files.keep_if{|f| f.key?(:width) or f.key?(:height)}.map{ |f|
|
74
|
+
f.transform_values(&:to_s).transform_keys(&:to_s)
|
75
|
+
}
|
76
|
+
|
77
|
+
output << parse_template.render({
|
78
|
+
'name' => @name,
|
79
|
+
'path' => @dd_dest,
|
80
|
+
'alt' => attr_value(:alt),
|
81
|
+
'title' => attr_value(:title),
|
82
|
+
'href' => attr_value(:href),
|
83
|
+
'caption' => attr_value(:caption),
|
84
|
+
'loading' => attr_value(:loading),
|
85
|
+
'sources' => filez,
|
86
|
+
'fallback_img' => fallback_img,
|
87
|
+
})
|
88
|
+
rescue Liquid::SyntaxError => l
|
89
|
+
unless Jekyll.env == 'production'.freeze
|
90
|
+
output << parse_template(name: 'error_code'.freeze).render({
|
91
|
+
'message' => l.message,
|
92
|
+
})
|
93
|
+
end
|
94
|
+
end
|
95
|
+
output
|
96
|
+
end
|
97
|
+
|
98
|
+
def static_file(*args)
|
99
|
+
Jekyll::DistorteD::Static::Image.new(*args)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
require 'distorted-jekyll/static/lastresort'
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module DistorteD
|
7
|
+
module Molecule
|
8
|
+
module LastResort
|
9
|
+
|
10
|
+
MEDIA_TYPE = 'lastresort'.freeze
|
11
|
+
|
12
|
+
# HACK HACK HACK
|
13
|
+
# Image Maps are a '90s Web relic, but I'm using this
|
14
|
+
# MIME::Type here to represent the generic fallback state.
|
15
|
+
# The MIME::Types library doesn't let me register custom
|
16
|
+
# types without shipping an entire custom type database,
|
17
|
+
# so I'm just going to use this since it will never
|
18
|
+
# be detected for a real file, and if it does then it will
|
19
|
+
# get an <img> tag anyway :)
|
20
|
+
MIME_TYPES = MIME::Types['application/x-imagemap'].to_set
|
21
|
+
|
22
|
+
ATTRS = Set[:alt, :title, :href, :caption]
|
23
|
+
ATTRS_DEFAULT = {}
|
24
|
+
ATTRS_VALUES = {}
|
25
|
+
|
26
|
+
def render_to_output_buffer(context, output)
|
27
|
+
super
|
28
|
+
begin
|
29
|
+
output << parse_template.render({
|
30
|
+
'name' => @name,
|
31
|
+
'basename' => File.basename(@name, '.*'),
|
32
|
+
'path' => @url,
|
33
|
+
'alt' => attr_value(:alt),
|
34
|
+
'title' => attr_value(:title),
|
35
|
+
'href' => attr_value(:href),
|
36
|
+
'caption' => attr_value(:caption),
|
37
|
+
})
|
38
|
+
rescue Liquid::SyntaxError => l
|
39
|
+
unless Jekyll.env == 'production'.freeze
|
40
|
+
output << parse_template(name: 'error_code'.freeze).render({
|
41
|
+
'message' => l.message,
|
42
|
+
})
|
43
|
+
end
|
44
|
+
end
|
45
|
+
output
|
46
|
+
end
|
47
|
+
|
48
|
+
def static_file(*args)
|
49
|
+
Jekyll::DistorteD::Static::LastResort.new(*args)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
require 'distorted/pdf'
|
4
|
+
require 'distorted-jekyll/static/pdf'
|
5
|
+
|
6
|
+
module Jekyll
|
7
|
+
module DistorteD
|
8
|
+
module Molecule
|
9
|
+
module PDF
|
10
|
+
|
11
|
+
# Reference these instead of reassigning them. Consistency is mandatory.
|
12
|
+
MEDIA_TYPE = Cooltrainer::DistorteD::PDF::MEDIA_TYPE
|
13
|
+
SUB_TYPE = Cooltrainer::DistorteD::PDF::SUB_TYPE
|
14
|
+
MIME_TYPES = Cooltrainer::DistorteD::PDF::MIME_TYPES
|
15
|
+
|
16
|
+
PDF_OPEN_PARAMS = Cooltrainer::DistorteD::PDF::PDF_OPEN_PARAMS
|
17
|
+
ATTRS = Cooltrainer::DistorteD::PDF::ATTRS
|
18
|
+
ATTRS_DEFAULT = Cooltrainer::DistorteD::PDF::ATTRS_DEFAULT
|
19
|
+
ATTRS_VALUES = Cooltrainer::DistorteD::PDF::ATTRS_VALUES
|
20
|
+
|
21
|
+
|
22
|
+
def render_to_output_buffer(context, output)
|
23
|
+
super
|
24
|
+
begin
|
25
|
+
# TODO: iOS treats our <object> like an <img>,
|
26
|
+
# showing only the first page with transparency and stretched to the
|
27
|
+
# size of the container element.
|
28
|
+
# We will need something like PDF.js in an <iframe> to handle this.
|
29
|
+
|
30
|
+
# Generate a Hash of our PDF Open Params based on any given to the Liquid tag
|
31
|
+
# and any loaded from the defaults.
|
32
|
+
# https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdf_open_parameters.pdf
|
33
|
+
pdf_open_params = PDF_OPEN_PARAMS.map{ |p|
|
34
|
+
if ATTRS_VALUES.dig(p) == Cooltrainer::DistorteD::PDF::BOOLEAN_SET
|
35
|
+
# Support multiple ways people might want to express a boolean
|
36
|
+
if Set[0, '0'.freeze, false, 'false'.freeze].include?(attr_value(p))
|
37
|
+
[p, '0'.freeze]
|
38
|
+
elsif Set[1, '1'.freeze, true, 'true'.freeze].include?(attr_value(p))
|
39
|
+
[p, '1'.freeze]
|
40
|
+
end
|
41
|
+
else
|
42
|
+
[p, attr_value(p)]
|
43
|
+
end
|
44
|
+
}.to_h
|
45
|
+
|
46
|
+
# Generate the URL fragment version of the PDF Open Params.
|
47
|
+
# This would be difficult / impossible to construct within Liquid
|
48
|
+
# from the individual variables, so let's just do it out here.
|
49
|
+
pdf_open_params_url = pdf_open_params.keep_if{ |p,v|
|
50
|
+
v != nil && v != ""
|
51
|
+
}.map{ |k,v|
|
52
|
+
# The PDF Open Params docs specify `search` should be quoted.
|
53
|
+
if k == :search
|
54
|
+
"#{k}=\"#{v}\""
|
55
|
+
else
|
56
|
+
"#{k}=#{v}"
|
57
|
+
end
|
58
|
+
}.join('&')
|
59
|
+
Jekyll.logger.debug("#{@name} PDF Open Params:", "#{pdf_open_params} #{"\u21e8".encode('utf-8').freeze} #{pdf_open_params_url}")
|
60
|
+
|
61
|
+
output << parse_template.render({
|
62
|
+
'name' => @name,
|
63
|
+
'path' => @dd_dest,
|
64
|
+
'alt' => attr_value(:alt),
|
65
|
+
'title' => attr_value(:title),
|
66
|
+
'height' => attr_value(:height),
|
67
|
+
'width' => attr_value(:width),
|
68
|
+
'caption' => attr_value(:caption),
|
69
|
+
'pdf_open_params' => pdf_open_params_url,
|
70
|
+
})
|
71
|
+
rescue Liquid::SyntaxError => l
|
72
|
+
unless Jekyll.env == 'production'.freeze
|
73
|
+
output << parse_template(name: 'error_code'.freeze).render({
|
74
|
+
'message' => l.message,
|
75
|
+
})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
output
|
79
|
+
end
|
80
|
+
|
81
|
+
def static_file(*args)
|
82
|
+
Jekyll::DistorteD::Static::PDF.new(*args)
|
83
|
+
end
|
84
|
+
|
85
|
+
end # PDF
|
86
|
+
end # Molecule
|
87
|
+
end # DistorteD
|
88
|
+
end # Jekyll
|