distorted-jekyll 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,62 @@
1
+ require 'set'
2
+
3
+ require 'distorted/molecule/font'
4
+
5
+
6
+ module Jekyll
7
+ module DistorteD
8
+ module Molecule
9
+ module Font
10
+
11
+ include Cooltrainer::DistorteD::Font
12
+
13
+ def render_to_output_buffer(context, output)
14
+ super
15
+ begin
16
+ filez = files.keep_if{ |f|
17
+ # Strip out all non-displayable media-types, e.g. the actual text/whatever.
18
+ f.key?(:type) && f&.dig(:type)&.media_type == 'image'.freeze
19
+ }.keep_if{ |f|
20
+ # Strip out full-size images (will have `nil`) — only display thumbnail vers
21
+ f.key?(:width) or f.key?(:height)
22
+ }.map{ |f|
23
+ # Stringify to make Liquid happy
24
+ f.transform_values(&:to_s).transform_keys(&:to_s)
25
+ }
26
+ output << parse_template.render({
27
+ 'name' => @name,
28
+ 'path' => @relative_dest,
29
+ 'alt' => abstract(:alt),
30
+ 'title' => abstract(:title),
31
+ 'sources' => filez,
32
+ 'fallback_img' => fallback_img,
33
+ })
34
+ rescue Liquid::SyntaxError => l
35
+ unless Jekyll.env == 'production'.freeze
36
+ output << parse_template(name: 'error_code'.freeze).render({
37
+ 'message' => l.message,
38
+ })
39
+ end
40
+ end
41
+ output
42
+ end
43
+
44
+ # Return the filename of the most-compatible output image
45
+ # for use as the fallback <img> tag inside our <picture>.
46
+ def fallback_img
47
+ best_ver = nil
48
+ files.keep_if{|f| f.key?(:type) && f&.dig(:type)&.media_type == 'image'.freeze}.each{ |f|
49
+ # PNG > WebP
50
+ if f&.dig(:type)&.sub_type == 'png'.freeze || best_ver.nil?
51
+ best_ver = f
52
+ end
53
+ }
54
+ # Return the filename of the biggest matched variation,
55
+ # otherwise use the original filename.
56
+ best_ver&.dig(:name) || @name
57
+ end
58
+
59
+ end # Font
60
+ end # Molecule
61
+ end # DistorteD
62
+ end # Jekyll
@@ -0,0 +1,94 @@
1
+ require 'set'
2
+
3
+ require 'distorted/molecule/image'
4
+
5
+
6
+ module Jekyll
7
+ module DistorteD
8
+ module Molecule
9
+ module Image
10
+
11
+ include Cooltrainer::DistorteD::Image
12
+
13
+ # Returns the filename we should use in the oldschool <img> tag
14
+ # as a fallback for <picture> sources. This file should be a cropped
15
+ # variation, the same MIME::Type as the input media, with the largest
16
+ # resolution possible.
17
+ # Failing that, use the filename of the original media.
18
+ # TODO: Handle situations when the input media_type is not in the
19
+ # Set of output media_types. We should pick the largest cropped variation
20
+ # of any type in that case.
21
+ def fallback_img
22
+ biggest_ver = nil
23
+
24
+ # Computes a Set of non-nil MIME::Type.sub_types for all MIME::Types
25
+ # detected for the original media file.
26
+ sub_types = type_mars.keep_if{ |m|
27
+ m.media_type == 'image'.freeze
28
+ }.map { |m|
29
+ m.sub_type
30
+ }.compact.to_set
31
+ files.keep_if{|f| f.key?(:width) or f.key?(:height)}.each{ |f|
32
+ if sub_types.include?(f[:type]&.sub_type)
33
+ if biggest_ver
34
+ if f[:width] > biggest_ver[:width]
35
+ biggest_ver = f
36
+ end
37
+ else
38
+ biggest_ver = f
39
+ end
40
+ end
41
+ }
42
+ # Return the filename of the biggest matched variation,
43
+ # otherwise use the original filename.
44
+ biggest_ver&.dig(:name) || @name
45
+ end
46
+
47
+ def outer_limits(*keys)
48
+ config = super
49
+ if config.empty?
50
+ Set[{
51
+ tag: :full,
52
+ crop: :none,
53
+ }]
54
+ else
55
+ config
56
+ end
57
+ end
58
+
59
+ def render_to_output_buffer(context, output)
60
+ super
61
+ begin
62
+ # Liquid doesn't seem able to reference symbolic keys,
63
+ # so convert everything to string for template.
64
+ # Remove full-size images from <sources> list before generating.
65
+ # Those should only be linked to, not displayed.
66
+ filez = files.keep_if{|f| f.key?(:width) or f.key?(:height)}.map{ |f|
67
+ f.transform_values(&:to_s).transform_keys(&:to_s)
68
+ }
69
+
70
+ output << parse_template.render({
71
+ 'name' => @name,
72
+ 'path' => @relative_dest,
73
+ 'alt' => abstract(:alt),
74
+ 'title' => abstract(:title),
75
+ 'href' => abstract(:href),
76
+ 'caption' => abstract(:caption),
77
+ 'loading' => abstract(:loading),
78
+ 'sources' => filez,
79
+ 'fallback_img' => fallback_img,
80
+ })
81
+ rescue Liquid::SyntaxError => l
82
+ unless Jekyll.env == 'production'.freeze
83
+ output << parse_template(name: 'error_code'.freeze).render({
84
+ 'message' => l.message,
85
+ })
86
+ end
87
+ end
88
+ output
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,51 @@
1
+ require 'set'
2
+
3
+ require 'distorted/checking_you_out'
4
+ require 'distorted/injection_of_love'
5
+
6
+ module Jekyll
7
+ module DistorteD
8
+ module Molecule
9
+ module LastResort
10
+
11
+
12
+ LOWER_WORLD = CHECKING::YOU::IN('application/x.distorted.last-resort')
13
+
14
+ ATTRIBUTES = Set[:alt, :title, :href, :caption]
15
+ ATTRIBUTES_DEFAULT = {}
16
+ ATTRIBUTES_VALUES = {}
17
+
18
+ # This is one of the few render methods that will be defined in JekyllLand.
19
+ define_method(CHECKING::YOU::IN('application/x.distorted.last-resort').first.distorted_method) { |*a, **k, &b|
20
+ copy_file(*a, **k, &b)
21
+ }
22
+
23
+ include Cooltrainer::DistorteD::InjectionOfLove
24
+
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' => @relative_dest,
33
+ 'alt' => abstract(:alt),
34
+ 'title' => abstract(:title),
35
+ 'href' => abstract(:href),
36
+ 'caption' => abstract(: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
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,79 @@
1
+ require 'set'
2
+
3
+ require 'distorted/molecule/pdf'
4
+
5
+
6
+ module Jekyll
7
+ module DistorteD
8
+ module Molecule
9
+ module PDF
10
+
11
+ include Cooltrainer::DistorteD::PDF
12
+
13
+
14
+ # Generate a Hash of our PDF Open Params based on any given to the Liquid tag
15
+ # and any loaded from the defaults.
16
+ # https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdf_open_parameters.pdf
17
+ def pdf_open_params
18
+ PDF_OPEN_PARAMS.map{ |p|
19
+ if ATTRIBUTES_VALUES.dig(p) == BOOLEAN_ATTR_VALUES
20
+ # Support multiple ways people might want to express a boolean
21
+ if Set[0, '0'.freeze, false, 'false'.freeze].include?(abstract(p))
22
+ [p, '0'.freeze]
23
+ elsif Set[1, '1'.freeze, true, 'true'.freeze].include?(abstract(p))
24
+ [p, '1'.freeze]
25
+ end
26
+ else
27
+ [p, abstract(p)]
28
+ end
29
+ }.to_h
30
+ end
31
+
32
+ # Generate the URL fragment version of the PDF Open Params.
33
+ # This would be difficult / impossible to construct within Liquid
34
+ # from the individual variables, so let's just do it out here.
35
+ def pdf_open_params_url
36
+ pdf_open_params.keep_if{ |p,v|
37
+ v != nil && v != ""
38
+ }.map{ |k,v|
39
+ # The PDF Open Params docs specify `search` should be quoted.
40
+ if k == :search
41
+ "#{k}=\"#{v}\""
42
+ else
43
+ "#{k}=#{v}"
44
+ end
45
+ }.join('&')
46
+ end
47
+
48
+ def render_to_output_buffer(context, output)
49
+ super
50
+ begin
51
+ # TODO: iOS treats our <object> like an <img>,
52
+ # showing only the first page with transparency and stretched to the
53
+ # size of the container element.
54
+ # We will need something like PDF.js in an <iframe> to handle this.
55
+
56
+ output << parse_template.render({
57
+ 'name' => @name,
58
+ 'path' => @relative_dest,
59
+ 'alt' => abstract(:alt),
60
+ 'title' => abstract(:title),
61
+ 'height' => abstract(:height),
62
+ 'width' => abstract(:width),
63
+ 'caption' => abstract(:caption),
64
+ 'pdf_open_params' => pdf_open_params_url,
65
+ })
66
+ rescue Liquid::SyntaxError => l
67
+ unless Jekyll.env == 'production'.freeze
68
+ output << parse_template(name: 'error_code'.freeze).render({
69
+ 'message' => l.message,
70
+ })
71
+ end
72
+ end
73
+ output
74
+ end
75
+
76
+ end # PDF
77
+ end # Molecule
78
+ end # DistorteD
79
+ end # Jekyll
@@ -0,0 +1,47 @@
1
+ require 'set'
2
+
3
+ require 'distorted/molecule/svg'
4
+
5
+
6
+ module Jekyll
7
+ module DistorteD
8
+ module Molecule
9
+ module SVG
10
+
11
+ include Cooltrainer::DistorteD::SVG
12
+
13
+ def render_to_output_buffer(context, output)
14
+ super
15
+ begin
16
+ # Liquid doesn't seem able to reference symbolic keys,
17
+ # so convert everything to string for template.
18
+ # Not stripping :full tags like Image because all of our
19
+ # SVG variations will be full-res for now.
20
+ filez = files.map{ |f|
21
+ f.transform_values(&:to_s).transform_keys(&:to_s)
22
+ }
23
+ output << parse_template.render({
24
+ 'name' => @name,
25
+ 'path' => @relative_dest,
26
+ 'alt' => abstract(:alt),
27
+ 'title' => abstract(:title),
28
+ 'href' => abstract(:href),
29
+ 'caption' => abstract(:caption),
30
+ 'loading' => abstract(:loading),
31
+ 'sources' => filez,
32
+ 'fallback_img' => @name,
33
+ })
34
+ rescue Liquid::SyntaxError => l
35
+ unless Jekyll.env == 'production'.freeze
36
+ output << parse_template(name: 'error_code'.freeze).render({
37
+ 'message' => l.message,
38
+ })
39
+ end
40
+ end
41
+ output
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,62 @@
1
+ require 'set'
2
+
3
+ require 'distorted/molecule/text'
4
+
5
+
6
+ module Jekyll
7
+ module DistorteD
8
+ module Molecule
9
+ module Text
10
+
11
+ include Cooltrainer::DistorteD::Text
12
+
13
+ def render_to_output_buffer(context, output)
14
+ super
15
+ begin
16
+ filez = files.keep_if{ |f|
17
+ # Strip out all non-displayable media-types, e.g. the actual text/whatever.
18
+ f.key?(:type) && f&.dig(:type)&.media_type == 'image'.freeze
19
+ }.keep_if{ |f|
20
+ # Strip out full-size images (will have `nil`) — only display thumbnail vers
21
+ f.key?(:width) or f.key?(:height)
22
+ }.map{ |f|
23
+ # Stringify to make Liquid happy
24
+ f.transform_values(&:to_s).transform_keys(&:to_s)
25
+ }
26
+ output << parse_template.render({
27
+ 'name' => @name,
28
+ 'path' => @relative_dest,
29
+ 'alt' => abstract(:alt),
30
+ 'title' => abstract(:title),
31
+ 'sources' => filez,
32
+ 'fallback_img' => fallback_img,
33
+ })
34
+ rescue Liquid::SyntaxError => l
35
+ unless Jekyll.env == 'production'.freeze
36
+ output << parse_template(name: 'error_code'.freeze).render({
37
+ 'message' => l.message,
38
+ })
39
+ end
40
+ end
41
+ output
42
+ end
43
+
44
+ # Return the filename of the most-compatible output image
45
+ # for use as the fallback <img> tag inside our <picture>.
46
+ def fallback_img
47
+ best_ver = nil
48
+ files.keep_if{|f| f.key?(:type) && f&.dig(:type)&.media_type == 'image'.freeze}.each{ |f|
49
+ # PNG > WebP
50
+ if f&.dig(:type)&.sub_type == 'png'.freeze || best_ver.nil?
51
+ best_ver = f
52
+ end
53
+ }
54
+ # Return the filename of the biggest matched variation,
55
+ # otherwise use the original filename.
56
+ best_ver&.dig(:name) || @name
57
+ end
58
+
59
+ end # Text
60
+ end # Molecule
61
+ end # DistorteD
62
+ end # Jekyll
@@ -0,0 +1,85 @@
1
+ require 'distorted/molecule/video'
2
+
3
+
4
+ module Jekyll
5
+ module DistorteD
6
+ module Molecule
7
+ module Video
8
+
9
+ include Cooltrainer::DistorteD::Video
10
+
11
+ def render_to_output_buffer(context, output)
12
+ super
13
+ begin
14
+ output << parse_template.render({
15
+ 'name' => @name,
16
+ 'basename' => File.basename(@name, '.*'),
17
+ 'path' => @url,
18
+ 'caption' => abstract(:caption),
19
+ })
20
+ rescue Liquid::SyntaxError => l
21
+ unless Jekyll.env == 'production'.freeze
22
+ output << parse_template(name: 'error_code'.freeze).render({
23
+ 'message' => l.message,
24
+ })
25
+ end
26
+ end
27
+ output
28
+ end
29
+
30
+ # Return a Set of extant video variations due to inability/unwillingness
31
+ # to exactly predict GStreamer's HLS/DASH segment output naming
32
+ # even if we are controlling all variables like segment length etc.
33
+ # This implementation may give stale segments but will at least speed
34
+ # up site generation by not having to regenerate the video every time.
35
+ def destinations(dest)
36
+ wanted = Set[]
37
+ if Dir.exist?(File.join(dest, @relative_dest))
38
+ hls_dir = File.join(dest, @relative_dest, "#{basename}.hls")
39
+ if Dir.exist?(hls_dir)
40
+ wanted.merge(Dir.entries(hls_dir).to_set.map{|f| File.join(hls_dir, f)})
41
+ end
42
+ end
43
+ wanted
44
+ end
45
+
46
+ def modified?
47
+ # We can't use the standard Static::State#modified? here until
48
+ # I figure out how to cleanly get a duplicate of what would be
49
+ # the generated filenames from GStreamer's sink.
50
+ #
51
+ # For now for the sake of speeding up my site generation
52
+ # I'll assume not-modified that if the output variant (e.g. DASH/HLS)
53
+ # container dir exists and contains at least two files:
54
+ # the playlist and at least one segment.
55
+ #
56
+ # Hacky HLS-only right now until dashsink2 lands in upstream Gst.
57
+ #
58
+ # Assume modified for the sake of freshness :)
59
+ modified = true
60
+
61
+ site_dest = Jekyll::DistorteD::Floor::config(:destination).to_s
62
+ if Dir.exist?(site_dest)
63
+
64
+ dd_dest = File.join(site_dest, @relative_dest)
65
+ if Dir.exist?(dd_dest)
66
+
67
+ hls_dir = File.join(dd_dest, "#{basename}.hls")
68
+ if Dir.exist?(hls_dir)
69
+ need_filez = Set["#{basename}.m3u8"]
70
+ var_filez = Dir.entries(hls_dir).to_set
71
+ if need_filez.subset?(var_filez) and var_filez.count > 2
72
+ modified = false
73
+ end
74
+ end
75
+
76
+ end
77
+ end
78
+ Jekyll.logger.debug("#{@name} modified?", modified)
79
+ modified
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+ end