jekyll_picture_tag 1.6.0 → 1.7.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/.rubocop.yml +2 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -2
- data/Rakefile +28 -0
- data/contributing.md +67 -0
- data/docs/examples/_config.yml +10 -0
- data/{examples → docs/examples}/_data/picture.yml +39 -19
- data/docs/examples/post.md +46 -0
- data/docs/global_configuration.md +115 -0
- data/docs/installation.md +30 -0
- data/docs/migration.md +178 -0
- data/docs/notes.md +85 -0
- data/docs/presets.md +407 -0
- data/docs/readme.md +23 -0
- data/docs/usage.md +131 -0
- data/jekyll-picture-tag.gemspec +3 -12
- data/jekyll_picture_tag.gemspec +8 -3
- data/lib/jekyll-picture-tag.rb +5 -3
- data/lib/jekyll_picture_tag.rb +45 -42
- data/lib/jekyll_picture_tag/defaults/global.yml +0 -3
- data/lib/jekyll_picture_tag/defaults/presets.yml +1 -0
- data/lib/jekyll_picture_tag/generated_image.rb +60 -39
- data/lib/jekyll_picture_tag/img_uri.rb +55 -0
- data/lib/jekyll_picture_tag/instructions.rb +1 -102
- data/lib/jekyll_picture_tag/instructions/configuration.rb +30 -74
- data/lib/jekyll_picture_tag/instructions/html_attributes.rb +18 -27
- data/lib/jekyll_picture_tag/instructions/preset.rb +14 -3
- data/lib/jekyll_picture_tag/instructions/set.rb +61 -0
- data/lib/jekyll_picture_tag/instructions/tag_parser.rb +80 -23
- data/lib/jekyll_picture_tag/output_formats.rb +1 -1
- data/lib/jekyll_picture_tag/output_formats/{basics.rb → basic.rb} +24 -19
- data/lib/jekyll_picture_tag/output_formats/data_attributes.rb +2 -2
- data/lib/jekyll_picture_tag/output_formats/direct_url.rb +1 -3
- data/lib/jekyll_picture_tag/output_formats/img.rb +4 -4
- data/lib/jekyll_picture_tag/output_formats/naked_srcset.rb +5 -4
- data/lib/jekyll_picture_tag/output_formats/picture.rb +6 -16
- data/lib/jekyll_picture_tag/output_formats/readme.md +8 -15
- data/lib/jekyll_picture_tag/router.rb +98 -0
- data/lib/jekyll_picture_tag/source_image.rb +15 -23
- data/lib/jekyll_picture_tag/srcsets.rb +1 -1
- data/lib/jekyll_picture_tag/srcsets/{basics.rb → basic.rb} +22 -13
- data/lib/jekyll_picture_tag/srcsets/pixel_ratio.rb +6 -11
- data/lib/jekyll_picture_tag/srcsets/width.rb +3 -11
- data/lib/jekyll_picture_tag/utils.rb +32 -49
- data/lib/jekyll_picture_tag/version.rb +1 -1
- data/readme.md +70 -70
- metadata +97 -16
- data/bin/console +0 -14
- data/bin/setup +0 -7
- data/examples/_config.yml +0 -4
- data/examples/post.md +0 -18
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'addressable'
|
2
|
+
|
3
|
+
module PictureTag
|
4
|
+
# Represents a link to an image. We use the File library rather than the URI
|
5
|
+
# library to build these because it doesn't like relative URIs.
|
6
|
+
#
|
7
|
+
# Just give it a filename, and pass source_image: true if it's not a generated
|
8
|
+
# image. Call to_s on it to get the link.
|
9
|
+
class ImgURI
|
10
|
+
attr_reader :filename, :source_image
|
11
|
+
def initialize(filename, source_image: false)
|
12
|
+
@source_image = source_image
|
13
|
+
@filename = filename
|
14
|
+
end
|
15
|
+
|
16
|
+
# https://example.com/my-base-path/assets/generated-images/image.jpg
|
17
|
+
# | domain | baseurl | directory | filename
|
18
|
+
def to_s
|
19
|
+
Addressable::URI.escape(
|
20
|
+
File.join(domain, baseurl, directory, @filename)
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# https://example.com/my-base-path/assets/generated-images/image.jpg
|
27
|
+
# ^^^^^^^^^^^^^^^^^^^^
|
28
|
+
# | domain | baseurl | j-p-t output dir | filename
|
29
|
+
def domain
|
30
|
+
if PictureTag.cdn?
|
31
|
+
PictureTag.pconfig['cdn_url']
|
32
|
+
elsif PictureTag.pconfig['relative_url']
|
33
|
+
''
|
34
|
+
else
|
35
|
+
PictureTag.config['url'] || ''
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# https://example.com/my-base-path/assets/generated-images/image.jpg
|
40
|
+
# ^^^^^^^^^^^^^
|
41
|
+
# | domain | baseurl | directory | filename
|
42
|
+
def baseurl
|
43
|
+
PictureTag.config['baseurl'] || ''
|
44
|
+
end
|
45
|
+
|
46
|
+
# https://example.com/my-base-path/assets/generated-images/image.jpg
|
47
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^
|
48
|
+
# | domain | baseurl | directory | filename
|
49
|
+
def directory
|
50
|
+
PictureTag.pconfig[
|
51
|
+
@source_image ? 'source' : 'output'
|
52
|
+
]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,106 +1,5 @@
|
|
1
|
+
require_relative './instructions/set'
|
1
2
|
require_relative './instructions/configuration'
|
2
3
|
require_relative './instructions/html_attributes'
|
3
4
|
require_relative './instructions/preset'
|
4
5
|
require_relative './instructions/tag_parser'
|
5
|
-
|
6
|
-
# Allows us to access settings as methods on PictureTag itself.
|
7
|
-
module PictureTag
|
8
|
-
class << self
|
9
|
-
attr_reader :context, :config, :params, :preset, :html_attributes
|
10
|
-
|
11
|
-
def init(raw_tag_params, context)
|
12
|
-
@context = context
|
13
|
-
|
14
|
-
# Create global config (big picture). Config class loads jekyll
|
15
|
-
# data/config files, and the j-p-t defaults from included yml files.
|
16
|
-
@config = Instructions::Configuration.new
|
17
|
-
|
18
|
-
# Parse tag params. We must do this before setting the preset, because
|
19
|
-
# it's one of the params.
|
20
|
-
@params = Instructions::TagParser.new(raw_tag_params)
|
21
|
-
|
22
|
-
# Create preset. Takes preset name from params, merges associated settings
|
23
|
-
# with default values.
|
24
|
-
@preset = Instructions::Preset.new
|
25
|
-
|
26
|
-
# Create HTML attributes. Depends on both the preset and tag params, so
|
27
|
-
# we must do this after creating both.
|
28
|
-
@html_attributes = Instructions::HTMLAttributeSet.new(
|
29
|
-
@params.html_attributes_raw
|
30
|
-
)
|
31
|
-
|
32
|
-
# Keep our generated files
|
33
|
-
Utils.keep_files
|
34
|
-
end
|
35
|
-
|
36
|
-
# Global site data
|
37
|
-
def site
|
38
|
-
@context.registers[:site]
|
39
|
-
end
|
40
|
-
|
41
|
-
# Page which tag is called from
|
42
|
-
def page
|
43
|
-
@context.registers[:page]
|
44
|
-
end
|
45
|
-
|
46
|
-
# Media query presets. It's really just a hash, and there are no default
|
47
|
-
# values, so extracting it to its own class is overkill.
|
48
|
-
def media_presets
|
49
|
-
site.data.dig('picture', 'media_presets') || {}
|
50
|
-
end
|
51
|
-
|
52
|
-
# The rest of the application doesn't care where the instruction logic
|
53
|
-
# resides. For example, I don't want to use PictureTag.config.source_dir and
|
54
|
-
# PictureTag.params.source_images, I just want to use PictureTag.source_dir
|
55
|
-
# and PictureTag.source_images. The following method definitions accomplish
|
56
|
-
# that.
|
57
|
-
|
58
|
-
# At first I thought I'd do some sweet dynamic metaprogramming here, but it
|
59
|
-
# ended up more complicated and clever than convenient. This way is not
|
60
|
-
# strictly DRY, but it's understandable and readable.
|
61
|
-
|
62
|
-
# Config Forwarding
|
63
|
-
def source_dir
|
64
|
-
@config.source_dir
|
65
|
-
end
|
66
|
-
|
67
|
-
def dest_dir
|
68
|
-
@config.dest_dir
|
69
|
-
end
|
70
|
-
|
71
|
-
def build_url(filename)
|
72
|
-
@config.build_url(filename)
|
73
|
-
end
|
74
|
-
|
75
|
-
def build_source_url(filename)
|
76
|
-
@config.build_source_url(filename)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Preset forwarding
|
80
|
-
def widths(media)
|
81
|
-
@preset.widths(media)
|
82
|
-
end
|
83
|
-
|
84
|
-
def fallback_format
|
85
|
-
@preset.fallback_format
|
86
|
-
end
|
87
|
-
|
88
|
-
def fallback_width
|
89
|
-
@preset.fallback_width
|
90
|
-
end
|
91
|
-
|
92
|
-
def nomarkdown?
|
93
|
-
@preset.nomarkdown?
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
# Params forwarding
|
98
|
-
def preset_name
|
99
|
-
@params.preset_name
|
100
|
-
end
|
101
|
-
|
102
|
-
def source_images
|
103
|
-
@params.source_images
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -3,12 +3,14 @@ module PictureTag
|
|
3
3
|
# Global config (big picture). loads jekyll data/config files, and the j-p-t
|
4
4
|
# defaults from included yml files.
|
5
5
|
class Configuration
|
6
|
-
|
7
|
-
|
6
|
+
# returns jekyll's configuration (picture is a subset)
|
7
|
+
def [](key)
|
8
|
+
content[key]
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
# picturetag specific configuration
|
12
|
+
def pconfig
|
13
|
+
content['picture']
|
12
14
|
end
|
13
15
|
|
14
16
|
# Digs into jekyll context, returns current environment
|
@@ -21,38 +23,22 @@ module PictureTag
|
|
21
23
|
# Site.source is the master jekyll source directory
|
22
24
|
# Source dir is the jekyll-picture-tag source directory.
|
23
25
|
def source_dir
|
24
|
-
File.join PictureTag.site.source,
|
26
|
+
File.join PictureTag.site.source, pconfig['source']
|
25
27
|
end
|
26
28
|
|
27
29
|
# site.dest is the master jekyll destination directory
|
28
30
|
# source_dest is the jekyll-picture-tag destination directory. (generated
|
29
31
|
# file location setting.)
|
30
32
|
def dest_dir
|
31
|
-
File.join PictureTag.site.dest,
|
32
|
-
end
|
33
|
-
|
34
|
-
# Generated images, not source images.
|
35
|
-
# https://example.com/my-base-path/assets/generated-images/image.jpg
|
36
|
-
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
37
|
-
# | domain | baseurl | j-p-t output dir | filename
|
38
|
-
def build_url(filename)
|
39
|
-
File.join url_prefix, self['picture']['output'], filename
|
40
|
-
end
|
41
|
-
|
42
|
-
# For linking source images
|
43
|
-
# https://example.com/my-base-path/assets/source-images/image.jpg
|
44
|
-
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
45
|
-
# | domain | baseurl | j-p-t source dir | filename
|
46
|
-
def build_source_url(filename)
|
47
|
-
File.join url_prefix, self['picture']['source'], filename
|
33
|
+
File.join PictureTag.site.dest, pconfig['output']
|
48
34
|
end
|
49
35
|
|
50
36
|
def nomarkdown?
|
51
|
-
Utils.markdown_page? &&
|
37
|
+
Utils.markdown_page? && pconfig['nomarkdown']
|
52
38
|
end
|
53
39
|
|
54
40
|
def continue_on_missing?
|
55
|
-
setting =
|
41
|
+
setting = pconfig['ignore_missing_images']
|
56
42
|
|
57
43
|
# Config setting can be a string, an array, or a boolean
|
58
44
|
if setting.is_a? Array
|
@@ -64,64 +50,34 @@ module PictureTag
|
|
64
50
|
end
|
65
51
|
end
|
66
52
|
|
67
|
-
|
68
|
-
|
69
|
-
def build_config
|
70
|
-
YAML.safe_load(
|
71
|
-
# Jekyll Picture Tag Default settings
|
72
|
-
File.read(
|
73
|
-
File.join(ROOT_PATH, 'jekyll_picture_tag/defaults/global.yml')
|
74
|
-
)
|
75
|
-
).merge(
|
76
|
-
# _config.yml defined settings
|
77
|
-
PictureTag.site.config
|
78
|
-
) do |_key, jpt_default, site_value|
|
79
|
-
setting_merge(jpt_default, site_value)
|
80
|
-
end
|
53
|
+
def cdn?
|
54
|
+
pconfig['cdn_url'] && pconfig['cdn_environments'].include?(jekyll_env)
|
81
55
|
end
|
82
56
|
|
83
|
-
|
84
|
-
if site_value.nil?
|
85
|
-
# Jekyll baseurl is nil if not configured, which breaks things.
|
86
|
-
# jpt_default is an empty string, which doesn't.
|
87
|
-
jpt_default
|
88
|
-
elsif site_value.is_a? Hash
|
89
|
-
# We'll merge hashes one level deep. If we need true deep merging,
|
90
|
-
# we'll import a gem or do something recursive.
|
91
|
-
jpt_default.merge site_value
|
92
|
-
else
|
93
|
-
site_value
|
94
|
-
end
|
95
|
-
end
|
57
|
+
private
|
96
58
|
|
97
|
-
|
98
|
-
|
99
|
-
self['picture']['cdn_url'] &&
|
100
|
-
self['picture']['cdn_environments'].include?(jekyll_env)
|
59
|
+
def content
|
60
|
+
@content ||= setting_merge(defaults, PictureTag.site.config)
|
101
61
|
end
|
102
62
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
''
|
111
|
-
else
|
112
|
-
self['url']
|
63
|
+
def setting_merge(default, jekyll)
|
64
|
+
jekyll.merge default do |_key, config_setting, default_setting|
|
65
|
+
if default_setting.respond_to? :merge
|
66
|
+
setting_merge(default_setting, config_setting)
|
67
|
+
else
|
68
|
+
config_setting
|
69
|
+
end
|
113
70
|
end
|
114
71
|
end
|
115
72
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
self['baseurl']
|
73
|
+
def defaults
|
74
|
+
# Jekyll Picture Tag Default settings
|
75
|
+
YAML.safe_load(
|
76
|
+
File.read(
|
77
|
+
File.join(
|
78
|
+
ROOT_PATH, 'jekyll_picture_tag/defaults/global.yml'
|
79
|
+
)
|
80
|
+
)
|
125
81
|
)
|
126
82
|
end
|
127
83
|
end
|
@@ -9,7 +9,7 @@ module PictureTag
|
|
9
9
|
@content = load_preset
|
10
10
|
|
11
11
|
parse_params(params) if params
|
12
|
-
|
12
|
+
handle_source_url
|
13
13
|
end
|
14
14
|
|
15
15
|
def [](key)
|
@@ -24,35 +24,26 @@ module PictureTag
|
|
24
24
|
|
25
25
|
# Syntax this function processes:
|
26
26
|
# class="old way" --picture class="new way" --alt Here's my alt text
|
27
|
-
def parse_params(
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
def parse_params(words)
|
28
|
+
key = 'implicit'
|
29
|
+
|
30
|
+
words.each do |word|
|
31
|
+
if word.match(/^--/)
|
32
|
+
key = word.delete_prefix('--')
|
33
|
+
elsif @content[key]
|
34
|
+
@content[key] << ' ' + word
|
35
|
+
else
|
36
|
+
@content[key] = word
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
32
40
|
|
33
|
-
|
34
|
-
|
41
|
+
def handle_source_url
|
42
|
+
return unless PictureTag.preset['link_source'] && self['link'].nil?
|
35
43
|
|
36
|
-
|
37
|
-
# Splits on spaces, the first word will be our key.
|
38
|
-
a = param.split
|
44
|
+
target = PictureTag.source_images.first.shortname
|
39
45
|
|
40
|
-
|
41
|
-
@content[a.shift] = a.join(' ')
|
42
|
-
end
|
43
|
-
end
|
44
|
-
# Handles anchor tag destination. Can come from 2 places in 2 formats:
|
45
|
-
# Can come from defaults, preset, or tag
|
46
|
-
# Default is false. Preset can specify either true or false
|
47
|
-
# Tag params can be a URL
|
48
|
-
|
49
|
-
# picture test.jpg --url http://example.com
|
50
|
-
def handle_url
|
51
|
-
return unless PictureTag.preset['link_source'] && !self['link']
|
52
|
-
|
53
|
-
@content['link'] = PictureTag.build_source_url(
|
54
|
-
Utils.biggest_source.shortname
|
55
|
-
)
|
46
|
+
@content['link'] = ImgURI.new(target, source_image: true).to_s
|
56
47
|
end
|
57
48
|
end
|
58
49
|
end
|
@@ -3,8 +3,8 @@ module PictureTag
|
|
3
3
|
# Handles the specific tag image set to construct.
|
4
4
|
class Preset
|
5
5
|
attr_reader :name
|
6
|
-
def initialize
|
7
|
-
@name =
|
6
|
+
def initialize(name)
|
7
|
+
@name = name
|
8
8
|
@content = build_preset
|
9
9
|
end
|
10
10
|
|
@@ -19,8 +19,12 @@ module PictureTag
|
|
19
19
|
width_hash[media]
|
20
20
|
end
|
21
21
|
|
22
|
+
def formats
|
23
|
+
@content['formats']
|
24
|
+
end
|
25
|
+
|
22
26
|
def fallback_format
|
23
|
-
|
27
|
+
@content['fallback_format']
|
24
28
|
end
|
25
29
|
|
26
30
|
def fallback_width
|
@@ -37,6 +41,13 @@ module PictureTag
|
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
44
|
+
def quality(format = nil)
|
45
|
+
qualities = @content['format_quality'] || {}
|
46
|
+
qualities.default = @content['quality']
|
47
|
+
|
48
|
+
qualities[format]
|
49
|
+
end
|
50
|
+
|
40
51
|
private
|
41
52
|
|
42
53
|
def build_preset
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Instructions
|
3
|
+
# Supervisor class, which manages all input handling and high level decision
|
4
|
+
# making which depends on it.
|
5
|
+
class Set
|
6
|
+
def initialize(raw_tag_params)
|
7
|
+
@raw_tag_params = raw_tag_params
|
8
|
+
end
|
9
|
+
|
10
|
+
def config
|
11
|
+
@config ||= Configuration.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def params
|
15
|
+
@params ||= TagParser.new @raw_tag_params
|
16
|
+
end
|
17
|
+
|
18
|
+
def preset
|
19
|
+
@preset ||= Preset.new params.preset_name
|
20
|
+
end
|
21
|
+
|
22
|
+
def html_attributes
|
23
|
+
# Depends on both the preset and tag params.
|
24
|
+
@html_attributes ||= HTMLAttributeSet.new params.leftovers
|
25
|
+
end
|
26
|
+
|
27
|
+
# These are our Media Query presets. It's really just a hash, and there
|
28
|
+
# are no default values, so extracting this to its own class is overkill.
|
29
|
+
def media_presets
|
30
|
+
PictureTag.site.data.dig('picture', 'media_presets') || {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def source_images
|
34
|
+
@source_images ||= build_source_images
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_source_images
|
38
|
+
source_names = params.source_names
|
39
|
+
media_presets = params.media_presets
|
40
|
+
|
41
|
+
sources = [SourceImage.new(source_names.shift)]
|
42
|
+
|
43
|
+
while params.source_names.any?
|
44
|
+
sources << SourceImage.new(
|
45
|
+
source_names.shift, media_presets.shift
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
sources
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns a class constant for the selected output format, which is used
|
53
|
+
# to dynamically instantiate it.
|
54
|
+
def output_class
|
55
|
+
Object.const_get(
|
56
|
+
'PictureTag::OutputFormats::' + Utils.titleize(preset['markup'])
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|