jekyll_img 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3b26f4329c93cd70afacb09303d63ac2d437b70b559403c0b4dfb0dbde060794
4
+ data.tar.gz: 9df636b6567ca51f02314d892a38a885032c8c320809fc4609dc83e82bcaf361
5
+ SHA512:
6
+ metadata.gz: fed0376534157a78447d4e5db766f9913833d0acddb41fb150d877ba35620f4b55fc3c89f986f695574930df89026ef4b02259f42ff71442cd3b340d595c07ec
7
+ data.tar.gz: b9ac7072163f1be7d578fe2705b75b5489c6379e5a91e30882263bb62a78dfe53dde295d8842c86e1f87b55016ba827d310af9491eb2b4f7fd84e0c584650de0
data/.rubocop.yml ADDED
@@ -0,0 +1,41 @@
1
+ AllCops:
2
+ Exclude:
3
+ - vendor/**/*
4
+ - exe/**/*
5
+ - Gemfile*
6
+ - Rakefile
7
+ NewCops: enable
8
+ TargetRubyVersion: 2.6
9
+
10
+ Layout/HashAlignment:
11
+ Enabled: false
12
+
13
+ Layout/LineLength:
14
+ Max: 150
15
+
16
+ Layout/MultilineMethodCallIndentation:
17
+ Enabled: false
18
+
19
+ Metrics/AbcSize:
20
+ Max: 40
21
+
22
+ Metrics/BlockLength:
23
+ Max: 30
24
+ Exclude:
25
+ - jekyll_img.gemspec
26
+ - spec/img_props_spec.rb
27
+
28
+ Metrics/CyclomaticComplexity:
29
+ Max: 10
30
+
31
+ Metrics/MethodLength:
32
+ Max: 30
33
+
34
+ Metrics/PerceivedComplexity:
35
+ Max: 10
36
+
37
+ Style/FrozenStringLiteralComment:
38
+ Enabled: false
39
+
40
+ Style/TrailingCommaInHashLiteral:
41
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ## 0.1.0 / 2023-01-12
2
+ * Initial version
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Mike Slinn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,173 @@
1
+ `jekyll_img`
2
+ [![Gem Version](https://badge.fury.io/rb/jekyll_img.svg)](https://badge.fury.io/rb/jekyll_img)
3
+ ===========
4
+
5
+ `Jekyll_img` is a Jekyll plugin that displays images,
6
+ and provides support for captions and URLs.
7
+
8
+ See [demo/index.html](demo/index.html) for examples.
9
+
10
+ Run the demo website by typing:
11
+ ```shell
12
+ $ demo/_bin/debug -r
13
+ ```
14
+ ... and point your web browser to http://localhost:4444
15
+
16
+
17
+ ## Usage
18
+ {% img [Options] src='path' %}
19
+
20
+ `Options` are:
21
+
22
+ - `align="left|inline|right|center"` Default value is `inline`
23
+ - `alt="Alt text"` Default value is the `caption` text, if provided
24
+ - `caption="A caption"` No default value
25
+ - `classes="class1 class2 classN"` Extra <img> classes; default is `rounded shadow`
26
+ - `id="someId"` No default value
27
+ - `nofollow` Generates `rel='nofollow'`; only applicable when `url` is specified
28
+ - `size='eighthsize|fullsize|halfsize|initial|quartersize|XXXYY|XXX%'`
29
+ Defines width of image.
30
+ - `initial` is the default behavior.
31
+ - `eighthsize`, `fullsize`, `halfsize`, and `quartersize` are relative to the enclosing tag's width.
32
+ - CSS units can also be used, for those cases `XXX` is a float and `YY` is `unit` (see below)
33
+ - `style='css goes here'` CSS style for <img>; no default
34
+ - `target='none|whatever'` Only applicable when `url` is specified; default value is `_blank`
35
+ - `title="A title"` Default value is `caption` text, if provided
36
+ - `url='https://domain.com'` No default value
37
+ - `wrapper_class='class1 class2 classN'` Extra CSS classes for wrapper <div>; no default value
38
+ - `wrapper_style='background-color: black;'` CSS style for wrapper <div>; no default value
39
+
40
+ [`unit`](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units#numbers_lengths_and_percentages) is one of: `Q`, `ch`, `cm`, `em`, `dvh`, `dvw`, `ex`, `in`, `lh`,
41
+ `lvh`, `lvw`, `mm`, `pc`, `px`, `pt`, `rem`, `rlh`, `svh`, `svw`, `vb`,
42
+ `vh`, `vi`, `vmax`, `vmin`, or `vw`.
43
+
44
+ CSS classes referenced by the `jekyll_img` plugin are at the bottom of [demo/assets/css/style.css](demo/assets/css/style.css). CSS marker classes are included, so CSS selectors can be used for additional styling.
45
+
46
+
47
+ ## Design
48
+ The most significant design issue was the decision that image size and formatting should not change
49
+ whether it had a caption.
50
+ HTML captions exist within a `<figure />` element, which also surrounds the image.
51
+
52
+ I also wanted to ensure that captions would wrap text under an image,
53
+ and would not be wider than the image they were associated with.
54
+
55
+ CSS behavior differs for `<figure />` and `<img />`.
56
+ For example, centering, floating right and left.
57
+ That means the CSS and where it would need to be applied are completely different for
58
+ naked `<img />` and `<figure />` tags.
59
+ Handling all possible situations of these two scenarios would significantly raise the complexity of the plugin code. I know, because I went down that rabbit hole.
60
+
61
+
62
+ ### Wrapper &lt;div /&gt;
63
+ To make the plugin code more manageable,
64
+ the plugin always encloses the generated HTML & CSS within a wrapper `<div />`.
65
+ The wrapper allows for a simple, consistent approach regardless of whether a caption is generated or not.
66
+
67
+ The wrapper width is identical to the displayed image width.
68
+ Within the wrapper `<div />`, the embedded `<img />` is displayed with `width=100%`.
69
+ If a caption is required, the generated `<figure />` only makes the space taken by the generated HTML longer;
70
+ the image width and height is not affected.
71
+
72
+ The wrapper will not exceed the width of the tag that encloses it if the `size` parameter has values `eighthsize`, `fullsize`, `halfsize`, `initial` or `quartersize`.
73
+
74
+ The wrapper's width can be defined independently of its enclosing tag by using [CSS units](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units#numbers_lengths_and_percentages) for the `size` parameter:
75
+ `Q`, `ch`, `cm`, `em`, `dvh`, `dvw`, `ex`, `in`, `lh`,
76
+ `lvh`, `lvw`, `mm`, `pc`, `px`, `pt`, `rem`, `rlh`, `svh`, `svw`, `vb`,
77
+ `vh`, `vi`, `vmax`, `vmin`, or `vw`.
78
+ Using CSS units means that large enough values could cause the image to exceed the width of its enclosing tag.
79
+
80
+
81
+ ## Installation
82
+
83
+ Add this line to your Jekyll project's Gemfile, within the `jekyll_plugins` group:
84
+
85
+ ```ruby
86
+ group :jekyll_plugins do
87
+ gem 'jekyll_img'
88
+ end
89
+ ```
90
+
91
+ Also add it to `_config.yml`:
92
+ ```yaml
93
+ plugins:
94
+ - jekyll_img
95
+ ```
96
+
97
+ And then execute:
98
+
99
+ $ bundle install
100
+
101
+
102
+ ## Additional Information
103
+ More information is available on
104
+ [Mike Slinn&rsquo;s website](https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html).
105
+
106
+
107
+ ## Development
108
+ After checking out the repo, run `bin/setup` to install dependencies.
109
+
110
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
111
+
112
+
113
+ To build and install this gem onto your local machine, run:
114
+ ```shell
115
+ $ bundle exec rake install
116
+ jekyll_img 0.1.0 built to pkg/jekyll_img-0.1.0.gem.
117
+ jekyll_img (0.1.0) installed.
118
+ ```
119
+
120
+ Examine the newly built gem:
121
+ ```shell
122
+ $ gem info jekyll_img
123
+
124
+ *** LOCAL GEMS ***
125
+
126
+ jekyll_img (0.1.0)
127
+ Author: Mike Slinn
128
+ Homepage:
129
+ https://github.com/mslinn/jekyll_img
130
+ License: MIT
131
+ Installed at: /home/mslinn/.gems
132
+
133
+ Generates Jekyll logger with colored output.
134
+ ```
135
+
136
+ ### Testing
137
+ Examine the output by running:
138
+ ```shell
139
+ $ demo/_bin/debug -r
140
+ ```
141
+ ... and pointing your web browser to http://localhost:4444/
142
+
143
+ ### Unit Tests
144
+ Either run `rspec` from Visual Studio Code's *Run and Debug* environment
145
+ (<kbd>Ctrl</kbd>-<kbd>shift</kbd>-<kbd>D</kbd>) and view the *Debug Console* output,
146
+ or run it from the command line:
147
+ ```shell
148
+ $ rspec
149
+ ```
150
+
151
+ ### Build and Push to RubyGems
152
+ To release a new version,
153
+ 1. Update the version number in `version.rb`.
154
+ 2. Commit all changes to git; if you don't the next step might fail with an unexplainable error message.
155
+ 3. Run the following:
156
+ ```shell
157
+ $ bundle exec rake release
158
+ ```
159
+ The above creates a git tag for the version, commits the created tag,
160
+ and pushes the new `.gem` file to [RubyGems.org](https://rubygems.org).
161
+
162
+
163
+ ## Contributing
164
+
165
+ 1. Fork the project
166
+ 2. Create a descriptively named feature branch
167
+ 3. Add your feature
168
+ 4. Submit a pull request
169
+
170
+
171
+ ## License
172
+
173
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task default: :spec
@@ -0,0 +1,42 @@
1
+ require_relative 'lib/jekyll_img/version'
2
+
3
+ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
4
+ github = 'https://github.com/mslinn/jekyll_img'
5
+
6
+ spec.bindir = 'exe'
7
+ spec.authors = ['Mike Slinn']
8
+ spec.email = ['mslinn@mslinn.com']
9
+ spec.files = Dir['.rubocop.yml', 'LICENSE.*', 'Rakefile', '{lib,spec}/**/*', '*.gemspec', '*.md']
10
+ spec.homepage = 'https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#quote'
11
+ spec.license = 'MIT'
12
+ spec.metadata = {
13
+ 'allowed_push_host' => 'https://rubygems.org',
14
+ 'bug_tracker_uri' => "#{github}/issues",
15
+ 'changelog_uri' => "#{github}/CHANGELOG.md",
16
+ 'homepage_uri' => spec.homepage,
17
+ 'source_code_uri' => github,
18
+ }
19
+ spec.name = 'jekyll_img'
20
+ spec.post_install_message = <<~END_MESSAGE
21
+
22
+ Thanks for installing #{spec.name}!
23
+
24
+ END_MESSAGE
25
+ spec.require_paths = ['lib']
26
+ spec.required_ruby_version = '>= 2.6.0'
27
+ spec.summary = 'Provides a Jekyll filter that creates formatted quotes.'
28
+ spec.test_files = spec.files.grep %r{^(test|spec|features)/}
29
+ spec.version = JekyllImgVersion::VERSION
30
+
31
+ spec.add_dependency 'jekyll', '>= 3.5.0'
32
+ spec.add_dependency 'jekyll_plugin_support', '>= 0.3.0'
33
+
34
+ # spec.add_development_dependency 'debase'
35
+ spec.add_development_dependency 'rspec'
36
+ spec.add_development_dependency 'rspec-match_ignoring_whitespace'
37
+ spec.add_development_dependency 'rubocop'
38
+ # spec.add_development_dependency 'rubocop-jekyll'
39
+ spec.add_development_dependency 'rubocop-rake'
40
+ spec.add_development_dependency 'rubocop-rspec'
41
+ spec.add_development_dependency 'ruby-debug-ide'
42
+ end
@@ -0,0 +1,75 @@
1
+ # Like RoR's squish method
2
+ class String
3
+ def squish
4
+ strip.gsub(/\s+/, ' ')
5
+ end
6
+ end
7
+
8
+ # Constructs HTML img tag from properties
9
+ class ImgBuilder
10
+ def initialize(props)
11
+ props.compute_dependant_properties
12
+ @props = props
13
+ end
14
+
15
+ def to_s
16
+ @props.compute_dependant_properties
17
+ generate_wrapper
18
+ end
19
+
20
+ private
21
+
22
+ def generate_wrapper
23
+ classes = "imgWrapper #{@props.img_display} #{@props.align} #{@props.attr_size_class} #{@props.wrapper_class}".squish
24
+ result = <<~END_HTML
25
+ <div class='#{classes}' style='#{@props.attr_width_style} #{@props.wrapper_style}'>
26
+ #{"<figure>\n" if @props.caption}
27
+ #{ if @props.url
28
+ "<a href='#{@props.url}'#{@props.attr_target}#{@props.attr_nofollow} class='imgImgUrl'>#{generate_img}</a>"
29
+ else
30
+ generate_img
31
+ end
32
+ }
33
+ #{generate_figure_caption}
34
+ #{"</figure>\n" if @props.caption}
35
+ </div>
36
+ END_HTML
37
+ result.strip
38
+ end
39
+
40
+ def generate_figure_caption
41
+ return nil unless @props.caption
42
+
43
+ <<~END_CAPTION
44
+ <figcaption class='imgFigCaption #{@props.attr_size_class}'>
45
+ #{if @props.url
46
+ <<~END_URL
47
+ <a href="#{@props.url}" #{@props.attr_target} #{@props.attr_nofollow}>
48
+ #{@props.caption}
49
+ </a>
50
+ END_URL
51
+ else
52
+ @props.caption
53
+ end
54
+ }
55
+ </figcaption>
56
+ END_CAPTION
57
+ end
58
+
59
+ # See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture
60
+ def generate_img
61
+ img_classes = @props.classes || 'rounded shadow'
62
+ <<~END_IMG
63
+ <picture#{@props.attr_id} class='imgPicture'>
64
+ <source srcset="#{@props.src}" type="image/webp">
65
+ <source srcset="#{@props.src_png}" type="image/png">
66
+ <img #{@props.attr_alt}
67
+ class="imgImg #{img_classes.squish}"
68
+ src="#{@props.src_png}"
69
+ #{@props.attr_style_img}
70
+ #{@props.attr_title}
71
+ />
72
+ </picture>
73
+ END_IMG
74
+ end
75
+ end
data/lib/img_props.rb ADDED
@@ -0,0 +1,97 @@
1
+ # Properties from user
2
+ # All methods are idempotent.
3
+ # attr_ methods can be called after compute_dependant_properties
4
+ # All methods except compute_dependant_properties can be called in any order
5
+ class ImgProperties
6
+ attr_accessor :align, :alt, :attr_wrapper_align_class, :caption, :classes, :id, :img_display, :nofollow, \
7
+ :src, :size, :style, :target, :title, :url, :wrapper_class, :wrapper_style
8
+
9
+ SIZES = %w[eighthsize fullsize halfsize initial quartersize].freeze
10
+
11
+ def attr_alt
12
+ "alt='#{@alt}'" if @alt
13
+ end
14
+
15
+ def attr_id
16
+ " id='#{@id}'" if @id
17
+ end
18
+
19
+ # <img> tag assets, except alignment classes (inline, left, center, right)
20
+ def attr_img_classes
21
+ @classes || 'rounded shadow'
22
+ end
23
+
24
+ def attr_nofollow
25
+ " rel='nofollow'" if @nofollow
26
+ end
27
+
28
+ def attr_size_class
29
+ return nil if @size.nil? || size_unit_specified?
30
+
31
+ abort "'#{@size}' is not a recognized size; must be one of #{SIZES.join(', ')}, or an explicit unit." \
32
+ unless SIZES.include?(@size)
33
+ @size
34
+ end
35
+
36
+ def attr_style_img
37
+ "style='width: 100%; #{@style}'".squish
38
+ end
39
+
40
+ def attr_target
41
+ return nil if @target == 'none'
42
+
43
+ target = @target || '_blank'
44
+ " target='#{target}'"
45
+ end
46
+
47
+ def attr_title
48
+ "title='#{@title}'" if @title && !@title.empty?
49
+ end
50
+
51
+ def attr_width_style
52
+ "width: #{@size};" if size_unit_specified?
53
+ end
54
+
55
+ def compute_dependant_properties
56
+ setup_src
57
+
58
+ @target ||= '_blank'
59
+
60
+ @img_display = @caption && @size ? 'imgBlock' : 'imgFlex'
61
+
62
+ @alt ||= @caption || @title
63
+ @title ||= @caption || @alt # rubocop:disable Naming/MemoizedInstanceVariableName
64
+ end
65
+
66
+ def src_png
67
+ abort 'src parameter was not specified' if @src.to_s.empty?
68
+
69
+ @src.gsub('.webp', '.png')
70
+ end
71
+
72
+ def self.local_path?(src)
73
+ first_char = src[0]
74
+ first_char.match?(%r{[./]})
75
+ end
76
+
77
+ private
78
+
79
+ def setup_src
80
+ @src = @src.to_s.strip
81
+ abort 'src parameter was not specified' if @src.empty?
82
+
83
+ @src = "/assets/images/#{@src}" unless ImgProperties.local_path?(@src) || url?(@src)
84
+ end
85
+
86
+ UNITS = %w[Q ch cm em dvh dvw ex in lh lvh lvw mm pc px pt rem rlh svh svw vb vh vi vmax vmin vw %].freeze
87
+
88
+ def size_unit_specified?
89
+ return false if @size.to_s.strip.empty?
90
+
91
+ @size.end_with?(*UNITS)
92
+ end
93
+
94
+ def url?(src)
95
+ src.start_with? 'http'
96
+ end
97
+ end
@@ -0,0 +1,3 @@
1
+ module JekyllImgVersion
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/jekyll_img.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'jekyll_plugin_support'
2
+ require 'jekyll_plugin_support_helper'
3
+ require_relative 'img_builder'
4
+ require_relative 'img_props'
5
+ require_relative 'jekyll_img/version'
6
+
7
+ # @author Copyright 2023 Michael Slinn
8
+ # @license SPDX-License-Identifier: Apache-2.0
9
+
10
+ module ImgModule
11
+ PLUGIN_NAME = 'img'.freeze
12
+ end
13
+
14
+ module Jekyll
15
+ # Plugin implementation
16
+ class Img < JekyllSupport::JekyllTag
17
+ def render_impl
18
+ props = ImgProperties.new
19
+ props.align = @helper.parameter_specified?('align') || 'inline'
20
+ props.alt = @helper.parameter_specified? 'alt'
21
+ props.caption = @helper.parameter_specified? 'caption'
22
+ props.classes = @helper.parameter_specified? 'class'
23
+ props.id = @helper.parameter_specified? 'id'
24
+ props.nofollow = @helper.parameter_specified? 'nofollow'
25
+ props.size = @helper.parameter_specified?('size') || @helper.parameter_specified?('_size')
26
+ props.src = @helper.parameter_specified? 'src'
27
+ props.style = @helper.parameter_specified? 'style'
28
+ props.target = @helper.parameter_specified? 'target'
29
+ props.title = @helper.parameter_specified? 'title'
30
+ props.url = @helper.parameter_specified? 'url'
31
+ props.wrapper_class = @helper.parameter_specified? 'wrapper_class'
32
+ props.wrapper_style = @helper.parameter_specified? 'wrapper_style'
33
+
34
+ @builder = ImgBuilder.new(props)
35
+ @builder.to_s
36
+ end
37
+ end
38
+ end
39
+
40
+ PluginMetaLogger.instance.info { "Loaded #{ImgModule::PLUGIN_NAME} v0.1.0 plugin." }
41
+ Liquid::Template.register_tag(ImgModule::PLUGIN_NAME, Jekyll::Img)
@@ -0,0 +1,64 @@
1
+ require 'rspec/match_ignoring_whitespace'
2
+ require_relative '../lib/img_builder'
3
+ require_relative '../lib/img_props'
4
+
5
+ # Test ImgProperties
6
+ class ImgPropertiesTest
7
+ RSpec.describe ImgBuilder do # rubocop:disable Metrics/BlockLength
8
+ it 'generates a default img' do
9
+ props = ImgProperties.new
10
+ props.src = 'blah.webp'
11
+ builder = ImgBuilder.new(props)
12
+ picture = <<~END_IMG
13
+ <div class='imgWrapper imgFlex' style=' '>
14
+ <picture class='imgPicture'>
15
+ <source srcset="/assets/images/blah.webp" type="image/webp">
16
+ <source srcset="/assets/images/blah.png" type="image/png">
17
+ <img class="imgImg rounded shadow"
18
+ src="/assets/images/blah.png"
19
+ style='width: 100%; '
20
+ />
21
+ </picture>
22
+ </div>
23
+ END_IMG
24
+
25
+ expect(builder.send(:generate_figure_caption)).to be nil
26
+ expect(builder.send(:generate_wrapper)).to match_ignoring_whitespace(picture)
27
+ end
28
+
29
+ it 'generates an img with size and caption' do
30
+ props = ImgProperties.new
31
+ props.caption = 'This is a caption'
32
+ props.size = '123px'
33
+ props.src = 'blah.webp'
34
+ builder = ImgBuilder.new(props)
35
+
36
+ caption = <<~END_CAPTION
37
+ <figcaption class='imgFigCaption '>
38
+ This is a caption
39
+ </figcaption>
40
+ END_CAPTION
41
+
42
+ picture = <<~END_IMG
43
+ <div class='imgWrapper imgBlock' style='width: 123px; '>
44
+ <figure>
45
+ <picture class='imgPicture'>
46
+ <source srcset="/assets/images/blah.webp" type="image/webp">
47
+ <source srcset="/assets/images/blah.png" type="image/png">
48
+ <img alt='This is a caption'
49
+ class="imgImg rounded shadow"
50
+ src="/assets/images/blah.png"
51
+ style='width: 100%; '
52
+ title='This is a caption'
53
+ />
54
+ </picture>
55
+ #{caption}
56
+ </figure>
57
+ </div>
58
+ END_IMG
59
+
60
+ expect(builder.send(:generate_figure_caption)).to match_ignoring_whitespace(caption)
61
+ expect(builder.send(:generate_wrapper)).to match_ignoring_whitespace(picture)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,112 @@
1
+ require_relative '../lib/img_props'
2
+
3
+ # Test ImgProperties
4
+ class ImgProperitesTest
5
+ RSpec.describe ImgProperties do # rubocop:disable Metrics/BlockLength
6
+ it 'detects relative paths' do
7
+ expect(ImgProperties.local_path?('abcdef')).to be false
8
+ expect(ImgProperties.local_path?('./abc')).to be true
9
+ expect(ImgProperties.local_path?('/abc')).to be true
10
+ end
11
+
12
+ it 'has other class methods' do
13
+ props = ImgProperties.new
14
+ expect(props.send(:size_unit_specified?)).to be false
15
+ expect(props.send(:url?, 'blah')).to be false
16
+ expect(props.send(:url?, 'http://blah')).to be true
17
+ end
18
+
19
+ it 'does not generate attributes for most empty properties' do
20
+ props = ImgProperties.new
21
+ expect(props.attr_alt).to be nil
22
+ expect(props.attr_img_classes).to eq('rounded shadow')
23
+ expect(props.attr_id).to be nil
24
+ expect(props.attr_nofollow).to be nil
25
+ expect(props.attr_size_class).to be nil
26
+ expect(props.attr_style_img).to eq("style='width: 100%; '")
27
+ expect(props.attr_target).to eq(" target='_blank'")
28
+ expect(props.attr_title).to be nil
29
+ expect(props.attr_width_style).to be nil
30
+
31
+ props.compute_dependant_properties
32
+ expect(props.attr_wrapper_align_class).to eq('inline')
33
+ end
34
+
35
+ it 'raises exception if src was not specified' do
36
+ props = ImgProperties.new
37
+ expect { props.src_png }.to raise_error(SystemExit)
38
+ expect { props.send(:setup_src) }.to raise_error(SystemExit)
39
+
40
+ props.src = 'relative/path.webp'
41
+ props.send(:setup_src)
42
+ expect(props.src).to eq('/assets/images/relative/path.webp')
43
+
44
+ props.src = './local/path.webp'
45
+ props.send(:setup_src)
46
+ expect(props.src).to eq('./local/path.webp')
47
+
48
+ props.src = '/absolute/path.webp'
49
+ props.send(:setup_src)
50
+ expect(props.src).to eq('/absolute/path.webp')
51
+ end
52
+
53
+ it 'generates proper simple attributes' do # rubocop:disable Metrics/BlockLength
54
+ props = ImgProperties.new
55
+
56
+ props.alt = 'blah'
57
+ expect(props.attr_alt).to eq("alt='blah'")
58
+
59
+ props.classes = 'blah'
60
+ expect(props.attr_img_classes).to eq('blah')
61
+
62
+ props.id = 'blah'
63
+ expect(props.attr_id).to eq(" id='blah'")
64
+
65
+ props.nofollow = true
66
+ expect(props.attr_nofollow).to eq(" rel='nofollow'")
67
+
68
+ props.size = 'initial'
69
+ expect(props.attr_size_class).to eq('initial')
70
+
71
+ props.size = '100px'
72
+ expect(props.attr_size_class).to be nil
73
+ expect(props.attr_style_img).to eq("style='max-width: 100px;'")
74
+ expect(props.attr_width_style).to eq('width: 100px;')
75
+
76
+ props.size = '10%'
77
+ expect(props.attr_size_class).to be nil
78
+ expect(props.attr_style_img).to eq("style='max-width: 10%;'")
79
+ expect(props.attr_width_style).to eq('width: 10%;')
80
+
81
+ props.size = 'fullsize'
82
+ expect(props.attr_size_class).to eq('fullsize')
83
+ expect(props.attr_width_style).to be nil
84
+
85
+ props.style = 'width: 30rem;'
86
+ expect(props.attr_style_img).to eq("style='width: 30rem;'")
87
+
88
+ props.target = 'moon'
89
+ expect(props.attr_target).to eq(" target='moon'")
90
+
91
+ props.title = 'The End'
92
+ expect(props.attr_title).to eq("title='The End'")
93
+
94
+ props.size = '100px'
95
+ props.caption = 'A caption'
96
+ expect(props.attr_size_class).to be nil
97
+ expect(props.attr_width_style).to eq('width: 100px;')
98
+ end
99
+
100
+ it 'generates proper alignment attributes' do
101
+ props = ImgProperties.new
102
+
103
+ props.align = 'inline'
104
+ props.compute_dependant_properties
105
+ expect(props.attr_wrapper_align_class).to eq('inline')
106
+
107
+ props.align = 'center'
108
+ props.compute_dependant_properties
109
+ expect(props.attr_wrapper_align_class).to eq('center')
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jekyll'
4
+ require 'jekyll_plugin_logger'
5
+ require 'rspec/match_ignoring_whitespace'
6
+ require_relative '../lib/jekyll_img'
7
+
8
+ Registers = Struct.new(:page, :site)
9
+
10
+ # Mock for Collections
11
+ class Collections
12
+ def values
13
+ []
14
+ end
15
+ end
16
+
17
+ # Mock for Site
18
+ class SiteMock
19
+ attr_reader :config
20
+
21
+ def collections
22
+ Collections.new
23
+ end
24
+ end
25
+
26
+ # Mock for Liquid::ParseContent
27
+ class TestParseContext < Liquid::ParseContext
28
+ attr_reader :line_number, :registers
29
+
30
+ def initialize
31
+ super
32
+ @line_number = 123
33
+
34
+ @registers = Registers.new(
35
+ { },
36
+ SiteMock.new
37
+ )
38
+ end
39
+ end
40
+
41
+ # These tests all fail because I have not figured out how to provide a Jekyll block body to a test
42
+ class MyTest
43
+ RSpec.describe Jekyll::Img do
44
+ let(:logger) do
45
+ PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
46
+ end
47
+
48
+ let(:parse_context) { TestParseContext.new }
49
+
50
+ let(:helper) do
51
+ JekyllPluginHelper.new(
52
+ 'img',
53
+ 'src="./blah.webp"',
54
+ logger
55
+ )
56
+ end
57
+
58
+ it 'has no cite or url' do
59
+ helper.reinitialize('src="./blah.webp"')
60
+ quote = Jekyll::Img.send(
61
+ :new,
62
+ 'img',
63
+ helper.markup.dup,
64
+ parse_context
65
+ )
66
+ result = quote.send(:render_impl, helper.markup)
67
+ expect(result).to match_ignoring_whitespace <<-END_RESULT
68
+ <img src="./blah.webp">
69
+ END_RESULT
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,11 @@
1
+ require 'jekyll'
2
+ require_relative '../lib/jekyll_img'
3
+
4
+ RSpec.configure do |config|
5
+ config.filter_run :focus
6
+ config.order = 'random'
7
+ config.run_all_when_everything_filtered = true
8
+
9
+ # See https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
10
+ config.example_status_persistence_file_path = 'spec/status_persistence.txt'
11
+ end
@@ -0,0 +1,10 @@
1
+ example_id | status | run_time |
2
+ ------------------------------- | ------ | --------------- |
3
+ ./spec/img_builder_spec.rb[1:1] | passed | 0.00073 seconds |
4
+ ./spec/img_props_spec.rb[1:1] | passed | 0.0001 seconds |
5
+ ./spec/img_props_spec.rb[1:2] | passed | 0.00008 seconds |
6
+ ./spec/img_props_spec.rb[1:3] | failed | 0.00051 seconds |
7
+ ./spec/img_props_spec.rb[1:4] | passed | 0.0011 seconds |
8
+ ./spec/img_props_spec.rb[1:5] | passed | 0.00019 seconds |
9
+ ./spec/img_props_spec.rb[1:6] | failed | 0.00008 seconds |
10
+ ./spec/jekyll_img_spec.rb[1:1] | failed | 0.00037 seconds |
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll_img
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mike Slinn
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 3.5.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.5.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: jekyll_plugin_support
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-match_ignoring_whitespace
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: ruby-debug-ide
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description:
126
+ email:
127
+ - mslinn@mslinn.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".rubocop.yml"
133
+ - CHANGELOG.md
134
+ - LICENSE.txt
135
+ - README.md
136
+ - Rakefile
137
+ - jekyll_img.gemspec
138
+ - lib/img_builder.rb
139
+ - lib/img_props.rb
140
+ - lib/jekyll_img.rb
141
+ - lib/jekyll_img/version.rb
142
+ - spec/img_builder_spec.rb
143
+ - spec/img_props_spec.rb
144
+ - spec/jekyll_img_spec.rb
145
+ - spec/spec_helper.rb
146
+ - spec/status_persistence.txt
147
+ homepage: https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#quote
148
+ licenses:
149
+ - MIT
150
+ metadata:
151
+ allowed_push_host: https://rubygems.org
152
+ bug_tracker_uri: https://github.com/mslinn/jekyll_img/issues
153
+ changelog_uri: https://github.com/mslinn/jekyll_img/CHANGELOG.md
154
+ homepage_uri: https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#quote
155
+ source_code_uri: https://github.com/mslinn/jekyll_img
156
+ post_install_message: |2+
157
+
158
+ Thanks for installing jekyll_img!
159
+
160
+ rdoc_options: []
161
+ require_paths:
162
+ - lib
163
+ required_ruby_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: 2.6.0
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ requirements: []
174
+ rubygems_version: 3.3.3
175
+ signing_key:
176
+ specification_version: 4
177
+ summary: Provides a Jekyll filter that creates formatted quotes.
178
+ test_files:
179
+ - spec/img_builder_spec.rb
180
+ - spec/img_props_spec.rb
181
+ - spec/jekyll_img_spec.rb
182
+ - spec/spec_helper.rb
183
+ - spec/status_persistence.txt
184
+ ...