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.
@@ -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